.NET

Reply
Member
bjmallon
Posts: 5
Registered: ‎11-18-2009
Message 1 of 1 (544 Views)

Linetypes : Reload all from .lin file including existing

544 Views, 0 Replies
05-12-2013 06:48 PM

Another contribution for those looking for help.

 

This one collects together the pieces from a few examples I came across that eventually helped me do what I wanted to do.

 

This code will load all the linetypes from a .lin file.  If the linetype exists, it will force a reload to ensure that the linetype is correctly defined.  This has been important for me as we have been noticing linetypes getting 'corrupted' occassionally with a disconnect between the linetype definition and the shapes being used in the linetype.  A reload has usually fixed it.

 

The 'CheckLinestyleExists' and 'GetLinestyleId' are included in case someone finds them useful.  I've got them as separate methods in case I just need that bit for another purpose.

 

They're all 'static' so that I can be a bit lazy calling them, without having to create an instance of the 'Utilities' class I've got the methods in.  It's working for me, I'm happy. :smileyhappy:

 

Here goes.  I hope someone finds it useful.

 

        /// <summary>
        /// Load all the linetypes contained in the passed in linetype file.
        /// If the linetype exists, a reload will be forced.
        /// </summary>
        /// <param name="LineTypeFile">Fully formed path to .lin file.  This is required for the StreamReader.</param>
        public static void LoadAllLinetypesFromFile(string LineTypeFile)
        {
            // In this case, my CommandFlags are set to 'Session'.
            // Therefore the document needs to be locked.
            DocumentLock docLock = Application.DocumentManager.MdiActiveDocument.LockDocument();

            using (docLock)
            {
                // Open, read the contents, and let go of the file.
                /* Most linetype files are not large enough to 
                 * generate any processing overheads with this method.
                 */
                StreamReader sr = new StreamReader(LineTypeFile);
                string fileContent = sr.ReadToEnd();
                sr.Close();

                // Split the contents of the file on new line/carriage return and jettison empty lines
                List<string> nameList = fileContent.Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries).ToList();

                // Trim the list down to linetype name lines only
                for (int i = nameList.Count - 1; i >= 0; i--)
                {
                    if (nameList[i].StartsWith(";")) // If the line starts with ';' it's a comment
                        nameList.RemoveAt(i);
                    else if (nameList[i].StartsWith("A")) // If the line starts with 'A' it's the definition itself.
                        nameList.RemoveAt(i);
                }

                // Process each name in the resulting list
                foreach (string name in nameList)
                {
                    // Regex out the name from the string.  We're not interested in the comment.
                    /* The 'name' line has the following format
                     * - *<Name>,<Description/comment>
                     * We're looking for anything between the '*' and the ','
                     * The Regex pattern is saying
                     * - '^' : from the start of the string
                     * - '\*' : starting with and '*', which needs to be escaped for Regex
                     * - '(?<Name>.*)' : Open a group called 'Name' accepting any character any number of times
                     * - ',' : The pattern is closed when a comma is encountered
                     */
                    string ltName = Regex.Match(name, @"^\*(?<Name>.*),").Groups["Name"].Value;
                    
                    LoadLinetype(LineTypeFile, ltName);
                }
            }
        }

        public static void LoadLinetype(string LineStyleFile, string LineStyle)
        {
            // Connect to the document
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;

            using (Transaction acTrans = db.TransactionManager.StartTransaction())
            {
                // Open the Linetype table for read
                LinetypeTable acLineTypTbl;
                acLineTypTbl = acTrans.GetObject(db.LinetypeTableId,
                    OpenMode.ForRead) as LinetypeTable;

                if (!acLineTypTbl.Has(LineStyle)) // If the linetype doesn't exist.
                    /* A Kean Walmsley example tries to load all linetypes by feeding "*" in as the linetype.
                     * That fails if the linetype exists.  
                     * Although he captures the exceptions, the remaining linetypes don't get loaded.
                     */
                    db.LoadLineTypeFile(LineStyle, LineStyleFile); // Load the requested Linetype.
                else
                    ForceLinetypeReload(LineStyleFile, LineStyle); // Force an update from the file.

                // Commit the changes
                acTrans.Commit();
            }
        }

        public static void ForceLinetypeReload(string LineStyleFile, string LineStyle)
        {
            /* I would like to acknowledge 'Hallex' on the Autodesk discussion forum for parts of this code.
             * I stripped out the bits that did what I needed them to do.
             * 
             * It was also the only post I've ever come across that actually demonstrated
             * how to use InvokeMember for the command sending.  Every other one just said
             * to 'use InvokeMember' without providing any context or requirements.
             * 
             * I salute you Hallex.  Many thanks.
             */
            // Get the current FILEDIA setting for restoration later
            Int16 fileDia = (Int16)Application.GetSystemVariable("FILEDIA");
            // Set FILEDIA to 0, to force a 'command line' interaction with the linetype command
            Application.SetSystemVariable("FILEDIA", 0);
            // Get an instance of the application object
            Object acObj = Application.AcadApplication;
            // Get an instance of the document objecy associated with the application
            object acDoc = acObj.GetType().InvokeMember("ActiveDocument", System.Reflection.BindingFlags.GetProperty, null, acObj, null);
            // Establish an array for the command
            object[] dataArray = new object[1];
            // Build the command string and add to the array
            dataArray[0] = "-linetype Load " + LineStyle + "\n" + LineStyleFile + "\nYes\n ";
            // Send the command to AutoCAD.
            acDoc.GetType().InvokeMember("SendCommand", System.Reflection.BindingFlags.InvokeMethod, null, acDoc, dataArray);
            // Reset the FILEDIA variable.
            Application.SetSystemVariable("FILEDIA", fileDia);
        }

        public static bool CheckLinestyleExists(string LineStyleName)
        {
            // Connect to the document and its database
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;

            // Transact with the database
            using (Transaction tr = db.TransactionManager.StartTransaction())
            {
                // Get an instance of the line type table
                LinetypeTable ltt = (LinetypeTable)tr.GetObject(db.LinetypeTableId, OpenMode.ForRead, true);
                // Test if the linetype exists
                if (ltt.Has(LineStyleName))
                    return true; // If it does return true

                return false; // If it doesn't return false
            }
        }

        public static ObjectId GetLinestyleID(string LineStyleName)
        {
            // Initialise a result
            ObjectId result = ObjectId.Null;

            // Connect to the document and its database
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;

            // Transact with the database
            Transaction tr = db.TransactionManager.StartTransaction();
            using (tr)
            {
                LinetypeTable ltt = (LinetypeTable)tr.GetObject(db.LinetypeTableId, OpenMode.ForRead); // Get an instance of the line type table
                if(ltt.Has(LineStyleName)) // IF the linestyle exists
                    result = ltt[LineStyleName]; // Get the linetype object id
                tr.Commit(); // Finish the transaction
            }

            return result;
        }

 

Post to the Community

Have questions about Autodesk products? Ask the community.

New Post
Announcements
Are You Going To Be @ AU 2014? Feel free to drop by our AU topic post and share your plans, plug a class that you're teaching, or simply check out who else from the community might be in attendance. Ohh and don't forgot to stop by the Autodesk Help | Learn | Collaborate booths in the Exhibit Hall and meet our community team if you get a chance!