.NET

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

Linetypes : Reload all from .lin file including existing

314 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;
        }

 

You are not logged in.

Log into access your profile, ask and answer questions, share ideas and more. Haven't signed up yet? Register

Announcements
Are you interested in helping shape the Autodesk Community?
We’re looking at a few different ways to improve the “All Forums” landing page and need your feedback! If interested, please take a few minutes to fill out the following Usability Study. Thank you for your time!

Need installation help?

Start with some of our most frequented solutions to get help installing your software.

Ask the Community