Sunday, October 24, 2010

Workin Hard?... or hardly workin?....

I've been working hard over the past few months... so I decided to go see some friends in Las Vegas... Any guesses as to what bar this photo was taken off of?...

Saturday, October 23, 2010

Angled Column Grid Workaround

I'll have to warn you that this post is 100% smoke and mirrors and should ONLY be used as a workaround for documenting existing buildings that use angled column grids...

As we all know, Revit will not let you have two column grids with the same name... but occasionally you may need to document an angled column grid (Revit does not support this as of version 2011). The image below illustrates the column grids in question (A and B).


So, here goes nothin

You will first need to create a new shared parameter formatted as text and name it something like "ColBubbleWorkaround."


You will need to then load this new shared parameter into your project and bind it to the Grids category as an instance parameter.



The next step in the process is to create the new Grid bubble type family. Open your current column grid bubble family and create two new Yes/No parameters named "ShowFakeBubble" and "ShowRealBubble."



These will be used to control the visibility for the current column grid bubble label and the other to control the visibility of a new label where you will add the above mentioned parameter "ColBubbleWorkaround" to display a general text override for your column bubble.


The next step is to create two new family types within the bubble family named "Fake Bubble Text" and "Real Bubble Text." Set the parameters for "ShowRealBubble" and "ShowFakeBubble" respectively for each of the types.


After you've loaded the family into your project you can set the new "fake" bubble family type to your column grid settings in your project. Select one of your column grids in the project and click the "Edit Type" button in the properties palette. Then change the symbol to the column grid symbol you want. You may want to duplicate the grid type so you can use the real column bubble for all grids that are not angled and the fake column grid type for the grids that you need to fake out...

Monday, October 18, 2010

Application Startup in Visual Startup Class Debug

If you've downloaded either of the C# or VB.NET free express versions of Microsoft Visual Studio 2010 and attempted to create any Revit Add-In class applications you may have noticed that there is no way to tell Visual Studio how to launch Revit for debug purposes.

You will have to manually open your .vbproj or .csproj file in in an ASCII text editor such as Notepad.exe and add a couple lines to accomplish debugging.

Open your .vbproj or .csproj file in notepad add the two lines that I have circled in the image below in the 'Debug|AnyCPU' group condition:

The StartAction must have a value of "Program" and the StartProgram attribute must contain the full path to the Revit executable file that you wish to use for debug. So besides a couple small nuisances, I think the Express versions of Visual Studio Express 2010 work just fins as long as you can live without any environment customizations...

Sunday, October 17, 2010

A BIM Based Facility and Workplace Management Web Site

If you want the details on how to build your own BIM Based Facility and Workplace Management Web Site, you'll have to attend my class in Autodesk University 2010 in Las Vegas.

Most notably, I will demonstrate how a 32 bit Microsoft Access database can be directly connected to and edited from a 64 bit session of Autodesk Revit Architecture using no special drivers or crazy configurations... The resulting database can then be used to serve the BIM Based Facility and Workplace Management Web Site.


I will be demonstrating how a BIM model can be configured and managed from a web environment. Notable page configurations will include:
  • A Searchable Employee Locator
  • 3D Floor Plan Device Query
  • Inventory Management
  • Energy Meter Management (Readings, etc), Graphical
  • How to manage external data using rooms as the parent element

Saturday, October 16, 2010

MS Access Recordset Handling

I showed how to create an instance of a 32 bit Microsoft Access database in a 64 bit Revit name space but I did not mention how to handle opening and updating recordset objects.

The dao.Recordset object provides the ability to open and update a recordset returned by a SQL select command.


''' <summary>
    ''' Returns a Recordset object from an Access Database
    ''' </summary>
    ''' <param name="tblName">Name of the table containing the record</param>
    ''' <param name="keyID">Field name</param>
    ''' <param name="keyValue">Field value to search for</param>
    ''' <returns>Recordset matching search criteria</returns>
    ''' <remarks></remarks>
    Public Function OpenRecordset(ByVal tblName As String, _
                                  ByVal keyID As String, _
                                  ByVal keyValue As String) As Access.Dao.Recordset
        Dim m_rs As Access.Dao.Recordset
        Dim SQL As String = "SELECT * FROM [" & tblName & "] WHERE ([" & keyID & "]='" & keyValue & "')"
        m_rs = m_DaoDB.OpenRecordset(SQL)
        Return m_rs
    End Function

Now with the m_rs object, the recordset can be modified using:

.Edit
m_rs.Fields("FieldName").Value = MyValue
.Update

You can get a value using:

MyValue = m_rs.Fields("FieldName").Value

Thursday, October 14, 2010

Closing the MS Access Session with Brute Force!

It can be tricky to kill a Microsoft Access database session by simply just closing it. The code below demosntrates how to close the application instance and release it entirely from memory using the Marshal technique.

BRUTE FORCE:


''' <summary>
    ''' Close and destroy on exit
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function CloseDB() As Boolean
        Try
            ' Close the database
            m_DaoDB.Close()
            ' Quit the application
            m_AccApp.Quit(Access.AcQuitOption.acQuitSaveAll)
            ' Marshal close just in case
            System.Runtime.InteropServices.Marshal.ReleaseComObject(m_AccApp)
            ' Destroy the main variables
            m_AccApp = Nothing
            m_DaoDB = Nothing
        Catch ex As Exception
            ' Close the database
            m_DaoDB.Close()
            ' Quit the application
            m_AccApp.Quit(Access.AcQuitOption.acQuitSaveAll)
            ' Marshal close just in case
            System.Runtime.InteropServices.Marshal.ReleaseComObject(m_AccApp)
            ' Destroy the main variables
            m_AccApp = Nothing
            m_DaoDB = Nothing
        End Try
    End Function

Programmatically Create a Relationship in Microsoft Access

Here is another of several Microsoft Access related posts I'll be sharing for handling a database interaction between 32 bit Microsoft Acces and a 64 bit session of Autodesk Revit 2011.

I've been asked several times recently how I am able to pragmatically create my table relationships in my Microsoft Access database setup utilities. As it turns out, the dao.Database object has a function built into it for doing just this but can be tricky to get it to actually work.

What you'll need to get this to work is an active dao.Database object, a primary table and primary key name, a foreign table and foreign key name, and a unique name for the relationship.

Sample code is provided below:

''' <summary>
    ''' Creates a relationship between two tables
    ''' </summary>
    ''' <param name="relName">Unique name for table relationship</param>
    ''' <param name="fkFieldName">Foreign Key Field Name</param>
    ''' <param name="pkFieldName">Primary Key Field Name</param>
    ''' <param name="TypeTableName">Top most table name</param>
    ''' <param name="InstTableName">Child table name</param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function CreateRelationship(ByVal relName As String, _
                           ByVal fkFieldName As String, _
                           ByVal pkFieldName As String, _
                           ByVal TypeTableName As String, _
                           ByVal InstTableName As String) As Boolean

        Dim rel As dao.Relation
        Dim fld As dao.Field

        Try
            rel = m_DaoDB.CreateRelation(relName, TypeTableName, InstTableName, dao.RelationAttributeEnum.dbRelationUpdateCascade)
            'GUID 'The field from the primary table.
            fld = rel.CreateField(pkFieldName)
            'xxGUID 'Matching field from the related table.
            fld.ForeignName = fkFieldName
            'primaryFieldName 'Add the field to the relation's Fields collection.
            rel.Fields.Append(fld)
            'Add the relation to the database.
            m_DaoDB.Relations.Append(rel)
            Return True
        Catch ex As Exception
            Return False
        End Try

    End Function

Wednesday, October 13, 2010

Autodesk University 2010... I Promise to Not Let You Down...

I'll be posting more often as we get closer to class time in Las Vegas. My material is coming together and might just be the best work I've done in a while.


I've decided to add my 100% rewritten Microsoft Access database "Autodesk Revit 2011 Incredilink" as a redistributable data set to get people what they need to really learn the Revit 2011 API! Some very unique and powerful Design Review 2011 API examples will also be presented! And again, the goal is to build a 100% custom web based (ASP.NET) FM/WM site using all 100% free software development tools.


The only real pain is that I only have one hour to present an entire Facility Management software package... It will be fast paced but will probably be the most feature rich AU class this year...

My AU2010 Class ID: CP333-1 goes down December 1 in Las Vegas!!!

64 Bit Revit and 32 Bit MS Access...

I've been told by several confused people that it is impossible to link a session of 64 bit Revit with a 32 bit session of a Microsoft Access database... this couldn't be further from the truth.

This does take a bit of monkeying around, but is totally possible even without some goofy fake 64 bit ODBC driver. s it turns out, Microsoft XP Pro 64 as well as Windows 7 64 ship and install with a file named "C:\Program Files (x86)\Common Files\Microsoft Shared\DAO\dao360.dll". The problem is that this file is not properly registered on the client machine when the operating system installs. Microsoft didn't even know this until I pointed it out to them in a service call. But wait, registering this file using the following REG script is not all that you need to do to get this to work:


There are three key references that need to be added to your project in order to take a Microsoft Access Database and connect to it as a "DAO" database object in a 64 bit name space that can support all the normal SQL commands and recordset functionality.

The bottom three references shown in the iamge above should be familiar for you, but the top three are specific to gaining access to the Microsoft Access database via the dao360.dll file! This functionality has been possible all along!

Here's how you generate the class to communicate with the database:


Imports Microsoft.Office.Interop
Imports Autodesk.Revit
Imports System.Diagnostics
Imports System.Reflection

''' &lt;summary>
''' A Class to create and interact with a session of Microsoft Access through a 64 bit namespace
''' &lt;/summary>
''' &lt;remarks>&lt;/remarks>
Public Class MSAccess64

    Private m_DaoDB As Access.Dao.Database
    Private m_AccApp As Access.ApplicationClass
    Private m_rs As Access.Dao.Recordset

    ''' &lt;summary>
    ''' Connect to a Microsoft Access Database
    ''' &lt;/summary>
    ''' &lt;param name="dbName">Valid file name and path to a Microsoft Access database&lt;/param>
    ''' &lt;param name="settings">A generic settings class&lt;/param>
    ''' &lt;remarks>&lt;/remarks>
    Public Sub New(ByVal dbName As String, ByVal settings As clsSettings)
        ' Test for valid filename
        If Dir$(dbName, FileAttribute.Directory) = "" Then
            MsgBox("Database File Not Found... ", MsgBoxStyle.Information, "Error")
            Exit Sub
        End If
        ' Creates a new Access session
        m_AccApp = New Access.ApplicationClass
        Try
            ' Opens the database filename in Access Session
            m_AccApp.OpenCurrentDatabase(dbName, Exclusive:=True)
            ' Requires access to dao
            ' Sets variable to new database object
            m_DaoDB = m_AccApp.CurrentDb
            ' Minimize app to tray
            MinimizeMsAccessApps()
        Catch ex As Exception
            MsgBox(Err.Description, MsgBoxStyle.Exclamation, Err.Source)
            If Dir$("C:\Program Files (x86)\Common Files\microsoft shared\DAO\dao360.dll", FileAttribute.Normal) = "" Then
                'Missing file error...
                MsgBox("64 bit ODBC interop file not found:" & vbCr & _
                       "C:\Program Files (x86)\Common Files\microsoft shared\DAO\dao360.dll" & vbCr & vbCr & _
                       "Error!", _
                       MsgBoxStyle.Exclamation, _
                       "Error Connecting to Database!")
            End If
            MsgBox("Error in attempting to open database interopabilty..." & vbCr & _
                   "Possibly due to a 64 bit limitation with ODBC..." & vbCr & vbCr & _
                   "Verify that dao360.dll has been properly registered and try again...", _
                   MsgBoxStyle.Exclamation, _
                   "Error Connecting to Database!")
        End Try

    End Sub

End Class