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.
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; }
Can't find what you're looking for? Ask the community or share your knowledge.