TheSwamp

Code Red => .NET => Topic started by: Kerry on January 27, 2010, 05:36:16 am

Title: .NET MISCELLANEOUS/GENERAL Routines
Post by: Kerry on January 27, 2010, 05:36:16 am
LIBRARY THREAD for  AutoCAD MISCELLANEOUS/GENERAL
 Members are encouraged to post any functions, methods, snips regarding
AutoCAD MISCELLANEOUS/GENERAL in .NET : C# ,  VB , F# , Python , etc

Feel free to include comments, descriptive notes, limitations,  and images to document your post.

Please post questions in a regular thread.
Title: Re: .NET MISCELLANEOUS/GENERAL Routines
Post by: Kerry on January 27, 2010, 05:44:39 am
I am using some of the free time offered by this holiday season to finish a routine I had originally posted at AUGI.

It is an alternative to the venerable TxtExp command (Express Tools Text Explode Text).  The main difference in my routine is that the underlying geometry is spline based.   That offers performance benefits over the faceted polylines in a few areas; reduced file size, better appearance, more manageable downstream data manipulation, etc.

Title: Re: .NET MISCELLANEOUS/GENERAL Routines
Post by: Chuck Gabriel on January 27, 2010, 10:03:17 am
PurgeAll command:

Code: [Select]
using System;
using System.Text;
using System.Collections.Generic;

using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.ApplicationServices;

[assembly: ExtensionApplication(typeof(cgabriel.PurgeTools))]
[assembly: CommandClass(typeof(cgabriel.PurgeTools))]

namespace cgabriel
{
    public class PurgeTools : IExtensionApplication
    {

        public void Initialize() { }
        public void Terminate() { }

        public static bool purgeSymbolTables(Database db, ObjectIdCollection tableIds, bool silent)
        {
            bool itemsPurged = false;
            Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;

            ObjectIdCollection purgeableIds = new ObjectIdCollection();
            using (Transaction tr = db.TransactionManager.StartTransaction())
            {
                foreach (ObjectId tableId in tableIds)
                {
                    SymbolTable table = (SymbolTable)tr.GetObject(tableId, OpenMode.ForRead, false);
                    foreach (ObjectId recordId in table)
                        purgeableIds.Add(recordId);
                }

                db.Purge(purgeableIds);

                if (purgeableIds.Count == 0) return false;
                itemsPurged = true;

                foreach (ObjectId id in purgeableIds)
                {
                    try
                    {
                        SymbolTableRecord record = (SymbolTableRecord)tr.GetObject(id, OpenMode.ForWrite);
                        string recordName = record.Name;
                        record.Erase();
                        if (!silent)
                        {
                            if (!recordName.Contains("|"))
                            {
                                ed.WriteMessage("\nPurging " + record.GetType().Name + " " + recordName);
                            }
                        }
                    }
                    catch (Autodesk.AutoCAD.Runtime.Exception e)
                    {
                        if ((e.ErrorStatus == ErrorStatus.CannotBeErasedByCaller) || (e.ErrorStatus == (ErrorStatus)20072))
                            itemsPurged = false;
                        else
                            throw e;
                    }
                }
                tr.Commit();
            }

            return itemsPurged;
        }

        public static bool purgeDictionaries(Database db, ObjectIdCollection dictIds, bool silent)
        {
            bool itemsPurged = false;
            Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;

            ObjectIdCollection purgeableIds = new ObjectIdCollection();
            using ( Transaction tr = db.TransactionManager.StartTransaction() )
            {
                foreach (ObjectId dictId in dictIds)
                {
                    DBDictionary dict = (DBDictionary)tr.GetObject(dictId, OpenMode.ForRead, false);
                    foreach (DBDictionaryEntry entry in dict)
                    {
                        purgeableIds.Add(entry.m_value);
                    }
                }

                db.Purge(purgeableIds);

                if (purgeableIds.Count == 0) return false;
                itemsPurged = true;

                DBDictionary nod = (DBDictionary)tr.GetObject(db.NamedObjectsDictionaryId, OpenMode.ForRead);
                foreach (ObjectId id in purgeableIds)
                {
                    try
                    {
                        DBObject obj = (DBObject)tr.GetObject(id, OpenMode.ForWrite);
                        obj.Erase();
                        if (!silent)
                        {
                            foreach (ObjectId dictId in dictIds)
                            {
                                DBDictionary dict = (DBDictionary)tr.GetObject(dictId, OpenMode.ForRead, false);
                                string dictName = nod.NameAt(dictId);
                                if (dict.Contains(id))
                                {
                                    ed.WriteMessage("\nPurging " + dict.NameAt(id) + " from " + dictName);
                                    break;
                                }
                            }
                        }
                    }
                    catch(Autodesk.AutoCAD.Runtime.Exception e)
                    {
                        if ((e.ErrorStatus == ErrorStatus.CannotBeErasedByCaller) || (e.ErrorStatus == (ErrorStatus)20072))
                            itemsPurged = false;
                        else
                            throw e;
                    }
                }

                tr.Commit();
            }

            return itemsPurged;
        }

        public static void purgeAll(Database db, bool silent)
        {
            ObjectIdCollection tableIds = new ObjectIdCollection();
            tableIds.Add(db.BlockTableId);
            tableIds.Add(db.DimStyleTableId);
            tableIds.Add(db.LayerTableId);
            tableIds.Add(db.LinetypeTableId);
            tableIds.Add(db.RegAppTableId);
            tableIds.Add(db.TextStyleTableId);
            tableIds.Add(db.UcsTableId);
            tableIds.Add(db.ViewportTableId);
            tableIds.Add(db.ViewTableId);
            ObjectIdCollection dictIds = new ObjectIdCollection();
            dictIds.Add(db.MaterialDictionaryId);
            dictIds.Add(db.MLStyleDictionaryId);
            dictIds.Add(db.MLeaderStyleDictionaryId);
            dictIds.Add(db.PlotStyleNameDictionaryId);
            dictIds.Add(db.TableStyleDictionaryId);
            dictIds.Add(db.VisualStyleDictionaryId);
            while (purgeSymbolTables(db, tableIds, silent) || purgeDictionaries(db, dictIds, silent))
                continue;
            return;
        }

        [CommandMethod("PurgeTools", "PurgeAll", CommandFlags.Modal | CommandFlags.DocExclusiveLock)]
        public static void purgeAll()
        {
            purgeAll(Application.DocumentManager.MdiActiveDocument.Database, false);
        }
    }
}
Title: Re: .NET MISCELLANEOUS/GENERAL Routines
Post by: Chuck Gabriel on January 27, 2010, 10:08:31 am
File dialogs for AutoLISP:

Code: [Select]
using System;
using System.IO;
using System.Text;

using Autodesk.AutoCAD.Windows;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.ApplicationServices;

using ofdFlags = Autodesk.AutoCAD.Windows.OpenFileDialog.OpenFileDialogFlags;
using sfdFlags = Autodesk.AutoCAD.Windows.SaveFileDialog.SaveFileDialogFlags;

namespace cgabriel
{
    public class LispFileDialogs
    {
        public static string title;
        public static string defaultFileName;
        public static string defaultExtension;
        public static short flags;

        [LispFunction("GetOpenFileDialog")]
        public static ResultBuffer GetOpenFileDialog(ResultBuffer args)
        {
            if (!parseArguments(args)) return null;

            ofdFlags dlgFlags = (ofdFlags)flags;
            if (((dlgFlags & ofdFlags.DefaultIsFolder) != 0) && Path.HasExtension(defaultFileName))
                defaultFileName = Path.GetDirectoryName(defaultFileName);

            OpenFileDialog dlg = new OpenFileDialog(title, defaultFileName, defaultExtension, title, dlgFlags);
            if (dlg.ShowDialog() != System.Windows.Forms.DialogResult.OK)
                return null;

            ResultBuffer result = new ResultBuffer();
            foreach (string file in dlg.GetFilenames())
                result.Add(new TypedValue((int)LispDataType.Text, file));
            return result;
        }

        [LispFunction("GetSaveFileDialog")]
        public static TypedValue GetSaveFileDialog(ResultBuffer args)
        {
            if (!parseArguments(args))
                return new TypedValue((int)LispDataType.Nil, null);
         
            sfdFlags dlgFlags = (sfdFlags)flags;
            if (((dlgFlags & sfdFlags.DefaultIsFolder) != 0) && Path.HasExtension(defaultFileName))
                defaultFileName = Path.GetDirectoryName(defaultFileName);

            SaveFileDialog dlg = new SaveFileDialog(title, defaultFileName, defaultExtension, title, dlgFlags);
            if (dlg.ShowDialog() != System.Windows.Forms.DialogResult.OK)
                return new TypedValue((int)LispDataType.Nil, null);

            return new TypedValue((int)LispDataType.Text, dlg.Filename);
        }

        public static bool parseArguments(ResultBuffer args)
        {
            Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
            if (args == null)
                return notEnoughArguments(ed);

            ResultBufferEnumerator iter = args.GetEnumerator();

            iter.MoveNext();
            if (iter.Current.TypeCode != (short)LispDataType.Text)
                return wrongArguments(ed);
            title = (string)iter.Current.Value;

            if (iter.MoveNext() == false)
                return notEnoughArguments(ed);
            if (iter.Current.TypeCode != (short)LispDataType.Text)
                return wrongArguments(ed);
            defaultFileName = (string)iter.Current.Value;

            if (iter.MoveNext() == false)
                return notEnoughArguments(ed);
            if (iter.Current.TypeCode != (short)LispDataType.Text)
                return wrongArguments(ed);
            defaultExtension = (string)iter.Current.Value;

            if (iter.MoveNext() == false)
                return notEnoughArguments(ed);
            if (iter.Current.TypeCode != (short)LispDataType.Int16)
                return wrongArguments(ed);
            flags = (short)iter.Current.Value;

            return true;
        }

        public static bool notEnoughArguments(Editor ed)
        {
            ed.WriteMessage("\nToo few arguments.");
            return false;
        }

        public static bool wrongArguments(Editor ed)
        {
            ed.WriteMessage("\nExpected string string string int.");
            return false;
        }
    }
}
Title: Re: .NET MISCELLANEOUS/GENERAL Routines
Post by: Chuck Gabriel on January 27, 2010, 03:55:36 pm
Toggle visibility of analytical elements in Revit Structure:

Code: [Select]
using System;
using System.Reflection;

using Autodesk.Revit;
using Autodesk.Revit.Elements;

namespace ToggleAnalyticalVisibility
{

    public class Toggles : IExternalApplication
    {
        public IExternalApplication.Result OnShutdown(ControlledApplication application)
        {
            return IExternalApplication.Result.Succeeded;
        }

        public IExternalApplication.Result OnStartup(ControlledApplication application)
        {
            Assembly library = Assembly.GetExecutingAssembly();
            string libraryPath = library.Location;
            MenuItem menuItem = application.CreateTopMenu("Analytical Model");
            menuItem.Append(
                MenuItem.MenuType.BasicMenu,
                "Hide Analytical Model Graphics",
                libraryPath,
                "ToggleAnalyticalVisibility.ToggleOff");
            menuItem.Append(
                MenuItem.MenuType.BasicMenu,
                "Show Analytical Model Graphics",
                libraryPath,
                "ToggleAnalyticalVisibility.ToggleOn");
            return IExternalApplication.Result.Succeeded;
        }
    }

    public class ToggleOn : IExternalCommand
    {
        public IExternalCommand.Result Execute(
            ExternalCommandData commandData,
            ref string message,
            ElementSet elements)
        {
            AnalyticalModelGraphics.setVisibility(commandData, true);
            return IExternalCommand.Result.Succeeded;
        }
    }

    public class ToggleOff : IExternalCommand
    {
        public IExternalCommand.Result Execute(
            ExternalCommandData commandData,
            ref string message,
            ElementSet elements)
        {
            AnalyticalModelGraphics.setVisibility(commandData, false);
            return IExternalCommand.Result.Succeeded;
        }
    }

    public class AnalyticalModelGraphics
    {
        public static void setVisibility(ExternalCommandData commandData, bool state)
        {
            Document doc = commandData.Application.ActiveDocument;
            View curView = doc.ActiveView;
            foreach (Category cat in doc.Settings.Categories)
            {
                if (cat.Name.ToLower().Contains("load"))
                {
                    curView.setVisibility(cat, state);
                }
                foreach (Category subCat in cat.SubCategories)
                {
                    if (subCat.Name.ToLower().Contains("analytical") ||
                        subCat.Name.ToLower().Contains("load"))
                    {
                        curView.setVisibility(subCat, state);
                    }
                }
            }

            // Believe it or not, the method used above is faster than that shown below in spite
            // of the fact that it iterates over every single category and subcategory.

            //Document doc = commandData.Application.ActiveDocument;
            //View curView = doc.ActiveView;
            //Settings settings = doc.Settings;
            //curView.setVisibility(
            //    settings.Categories.get_Item(BuiltInCategory.OST_AnalyticalRigidLinks),
            //    state);
            //curView.setVisibility(
            //    settings.Categories.get_Item(BuiltInCategory.OST_ColumnAnalyticalGeometry),
            //    state);
            //curView.setVisibility(
            //    settings.Categories.get_Item(BuiltInCategory.OST_ColumnAnalyticalRigidLinks),
            //    state);
            //curView.setVisibility(
            //    settings.Categories.get_Item(BuiltInCategory.OST_FloorsAnalyticalGeometry),
            //    state);
            //curView.setVisibility(
            //    settings.Categories.get_Item(BuiltInCategory.OST_FootingAnalyticalGeometry),
            //    state);
            //curView.setVisibility(
            //    settings.Categories.get_Item(BuiltInCategory.OST_FramingAnalyticalGeometry),
            //    state);
            //curView.setVisibility(
            //    settings.Categories.get_Item(BuiltInCategory.OST_WallsAnalyticalGeometry),
            //    state);

        }
    }
}
Title: Re: .NET MISCELLANEOUS/GENERAL Routines
Post by: gile on February 05, 2010, 11:51:29 am
Hi,

A custom osnaps example here (http://www.theswamp.org/index.php?topic=32031.0).
Title: Re: .NET MISCELLANEOUS/GENERAL Routines
Post by: fixo on February 13, 2010, 05:41:37 pm
Quick way to parse text file
Code: [Select]
    Public Function ReadCSV(ByVal filename As String, ByVal sep As String) As List(Of String())
        Dim info As List(Of String()) = New List(Of String())
        Using pars As New FileIO.TextFieldParser(filename)
            pars.SetDelimiters(sep)
            While Not pars.EndOfData
                Dim line() As String
                line = pars.ReadFields()
                info.Add(line)
            End While
        End Using
        Return info
    End Function
~'J'~
Title: Re: .NET MISCELLANEOUS/GENERAL Routines
Post by: fixo on February 19, 2010, 05:28:32 am
Fast way to read data from Excel

-Create Windows Application project
-Drop button1 and dataGridView1 on form
-Change full path of Excel file
Enjoy  :-)

Code: [Select]

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Data.OleDb;
using System.Reflection;
using System.Runtime.InteropServices;
using System.IO;
using System.Windows.Forms;

namespace ReadExcelJet
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        public static void ReadXlWithJet(ref DataGridView dgv)
        {
            // create connection string
            // 'HDR=YES' it means that excel table has headers otherwise write 'HDR=NO'
            string strcon = "Provider=Microsoft.Jet.OLEDB.4.0;" + "Data Source=" + @"c:\Points.xls;" + "Extended Properties=\"Excel 8.0;HDR=YES\"";
            // create connection
            OleDbConnection conn = new OleDbConnection(strcon);
            //create data adapter
            //[Sheet1$A1:C] it means the first 3 columns from Sheet1
            OleDbDataAdapter da = new OleDbDataAdapter("SELECT * FROM [Sheet1$A1:C]", conn);
            //create new dataset
            DataSet ds = new DataSet();
            // fill dataset
            da.Fill(ds);
            //populate grid with data
            dgv.DataSource = ds.Tables[0];
            //close connection
            conn.Close();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            //clear datagridview
            dataGridView1.DataSource = null;
            dataGridView1.ColumnCount = 0;
            //populate datagridview
            ReadXlWithJet(ref dataGridView1);
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            dataGridView1.AllowUserToAddRows = false;//<-- to do not draw empty row at the bottom of grid
            dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
            //adding some flowers in there
            dataGridView1.ForeColor = Color.Navy;
            dataGridView1.GridColor = Color.DarkGreen;
        }
    }
}

~'J'~
Title: Re: .NET MISCELLANEOUS/GENERAL Routines
Post by: Kerry on February 19, 2010, 05:31:31 am

I don't think this will work in x64 bit

"Provider=Microsoft.Jet.OLEDB.4.0;"

Microsoft are not producing a 64 bit Jet driver ( by my understanding)

... but I;d like to be told I'm wrong.
Title: Re: .NET MISCELLANEOUS/GENERAL Routines
Post by: fixo on February 19, 2010, 06:11:55 am

I don't think this will work in x64 bit

"Provider=Microsoft.Jet.OLEDB.4.0;"

Microsoft are not producing a 64 bit Jet driver ( by my understanding)

... but I;d like to be told I'm wrong.

Still working in A2008

~'J'~
Title: Re: .NET MISCELLANEOUS/GENERAL Routines
Post by: fixo on February 19, 2010, 06:54:50 am
Read / Write Excel examples
(it is necessary to change the file name in the code)

===  VB.NET  ===

Code: [Select]
Imports System.Runtime.InteropServices
Imports System.Globalization
Imports System.Threading
Imports Microsoft.Office.Interop.Excel
Imports Excel = Microsoft.Office.Interop.Excel
'' References -> COM -> Microsoft.Excel XX.0 Object Library
'' Create form and drop Button1 and ListView1 on form

Public Class Form1

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        '' This line is very important!
        Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("en-US") '<-- change culture on

whatever you need
        Dim miss As Object = System.Reflection.Missing.Value
        Dim i As Integer
        Dim j As Integer
        '' Open Excel
        Dim m_objExcel As Excel.Application = New Excel.Application
        m_objExcel.Visible = True
        Dim m_objBooks As Workbooks = m_objExcel.Workbooks
        Try
            '' Open workbook
            m_objBooks.Open("C:\Points.xls", False, False, miss, "", False, miss, Excel.XlPlatform.xlWindows, miss, True,

miss, miss, miss, False)

            Dim m_objBook As Workbook = m_objBooks.Item(1)
            m_objBook.Activate() 'optional
            Dim m_objSheets As Sheets = m_objBook.Sheets
            Dim m_objSheet As Worksheet = m_objSheets.Item(2) '<--"Sheet2"
            m_objSheet.Cells.ClearContents() 'optional
            Dim m_objCells As Range = m_objSheet.Cells

            '' write data starting from cell "A1"
            Dim m_objRange As Range = Nothing
            For i = 1 To 101
                For j = 1 To 3
                    m_objRange = m_objSheet.Range(m_objCells(i, j), m_objCells(i, j))
                    m_objRange.Value = Rnd(5).ToString
                Next
            Next

            '' fill the listview with data
            ListView1.Clear()
            Dim columns() As String = New String() {"X coordinate", "Y coordinate", "Z coordinate"}

            For Each column As String In columns
                ListView1.Columns.Add(column, 96, HorizontalAlignment.Left)
            Next

            ListView1.View = View.Details
            ListView1.GridLines = True
            ListView1.FullRowSelect = True

            For row As Integer = 1 To i - 1

                Dim lvi As New ListViewItem(m_objSheet.Range(m_objCells(row, 1), m_objCells(row, 1)).Value.ToString, 0)
                For col As Integer = 2 To j - 1
                    lvi.SubItems.Add(m_objSheet.Range(m_objCells(row, col), m_objCells(row, col)).Value.ToString)
                Next
                Me.ListView1.Items.Add(lvi)
            Next

            '' Save the file in the typical workbook format
            m_objBook.SaveAs("C:\Points.xls", Excel.XlFileFormat.xlWorkbookNormal, "", "", False, False,

XlSaveAsAccessMode.xlNoChange, miss, miss, miss, miss, miss)
            '' close workbook and quit Excel
            m_objBook.Close(False, miss, miss)
            m_objExcel.Quit()
        Catch ex As System.Exception
            MessageBox.Show(ex.StackTrace)
        Finally
            '' release process if it's still active
            System.Runtime.InteropServices.Marshal.FinalReleaseComObject(m_objExcel)
        End Try
    End Sub

End Class

===  C#  ===

Code: [Select]
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

using System.Runtime.InteropServices;
using System.Globalization;
using System.Threading;
using Microsoft.Office.Interop.Excel;
using Excel = Microsoft.Office.Interop.Excel;

//' References -> COM -> Microsoft.Excel XX.0 Object Library
//' Create form and drop Button1 and ListView1 on it
namespace ExcelForumCS
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Button1_Click(object sender, EventArgs e)
        {
            //' This line is very important!
            Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("en-US");  //<-- change culture on

whatever you need
            object miss = System.Reflection.Missing.Value;
            int i = 0;
            int j = 0;
            //' Open Excel
            Excel.Application m_objExcel = new Excel.Application();
            m_objExcel.Visible = true;
            Workbooks m_objBooks = m_objExcel.Workbooks;
            try
            {
                //' Open workbook

                m_objBooks.Open("C:\\Points.xls", false, false, miss, "", miss, miss, miss, miss, true, miss, miss, miss, miss,

miss);

                Workbook m_objBook = m_objBooks.get_Item(1);
                //m_objBook.Activate();//optional
                Sheets m_objSheets = m_objBook.Sheets;
                Worksheet m_objSheet = (Worksheet)m_objSheets.get_Item(1); //<--"Sheet1"
                m_objSheet.Cells.ClearContents();
                //optional
                Range m_objCells = m_objSheet.Cells;

                //' write data starting from cell "A1"
                Range m_objRange = null;
                Random rand = new Random();
                for (i = 1; i <= 25; i++)//25 - number of rows
                {
                    for (j = 1; j <= 3; j++)//3 - number of point ordinates
                    {
                        m_objRange = m_objSheet.get_Range(m_objCells[i, j], m_objCells[i, j]);
                        m_objRange.set_Value(miss, (i * 0.12345 * rand.Next(1,10)).ToString());//<--set dummy value
                    }
                }

                //' fill the listview with data
                ListView1.Clear();
                string[] columns = new string[] { "X coordinate", "Y coordinate", "Z coordinate" };

                foreach (string column in columns)
                {
                    ListView1.Columns.Add(column, 96, HorizontalAlignment.Left);
                }

                ListView1.View = View.Details;
                ListView1.GridLines = true;
                ListView1.FullRowSelect = true;

                for (int row = 1; row <= i - 1; row++)
                {

                    ListViewItem lvi = new ListViewItem(m_objSheet.get_Range(m_objCells[row, 1], m_objCells[row,

1]).Value2.ToString(), 0);
                    for (int col = 2; col <= j - 1; col++)
                    {

                        lvi.SubItems.Add(m_objSheet.get_Range(m_objCells[row, 1], m_objCells[row, 1]).Value2.ToString());
                    }
                    this.ListView1.Items.Add(lvi);
                }

                //' Save the file in the typical workbook format
                m_objBook.SaveAs("C:\\Points.xls", Excel.XlFileFormat.xlWorkbookNormal, "", "", false, false,

XlSaveAsAccessMode.xlNoChange, miss, miss, miss,
                miss, miss);
                //' close workbook and quit Excel
                m_objBook.Close(false, miss, miss);
                m_objExcel.Quit();
            }
            catch (System.Exception ex)
            {
                MessageBox.Show(ex.StackTrace);
            }
            finally
            {
                //' release process if it's still active
                System.Runtime.InteropServices.Marshal.FinalReleaseComObject(m_objExcel);
            }
        }
}
    }

~'J'~

Title: Re: .NET MISCELLANEOUS/GENERAL Routines
Post by: fixo on February 25, 2010, 02:38:29 am
Working with OpenOffice Calc document

Code: [Select]

using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
using System.Text.RegularExpressions;
//require references to all "cli_*.dll's files from:
//C:/Program Files/OpenOffice 3.0/openofficeorg1.cab/
// set Copy Local = false
//set Specific Version = false
using unoidl.com.sun.star.system;
using unoidl.com.sun.star.lang;
using unoidl.com.sun.star.uno;
using unoidl.com.sun.star.bridge;
using unoidl.com.sun.star.frame;
using unoidl.com.sun.star.text;
using unoidl.com.sun.star.beans;
using unoidl.com.sun.star.sheet;
using unoidl.com.sun.star.container;
using unoidl.com.sun.star.table;


//See original article from there:
//http://c-programming.suite101.com/article.cfm/creating_an_openoffice_calc_document_with_c
namespace OOfficeExm
{
    public class OOfficeTools
    {
        /// <summary>
        ///                 * Write data into the existing Calc document *
        /// </summary>
        public static void WriteToExistingCalc()
        {
            //file name is with back slashes in the OOffice format only:
            string fileName = @"file:///C:/test.ods";
            //The first step is to use
            //the bootstrap method to start OpenOffice.org (or to access any existing instances):
            XComponentContext oStrap = uno.util.Bootstrap.bootstrap();
            //The next step is to use OpenOffice.org's service manager to create a desktop:
            XMultiServiceFactory oServMan = (XMultiServiceFactory)oStrap.getServiceManager();
            XComponentLoader oDesk = (XComponentLoader)oServMan.createInstance("com.sun.star.frame.Desktop");

            PropertyValue[] propVals = new PropertyValue[0];
            //And then an existing Calc document is added to the desktop:
            XComponent oDoc = oDesk.loadComponentFromURL(fileName, "_private:stream", 0, propVals);//OK
            XSpreadsheets oSheets = ((XSpreadsheetDocument)oDoc).getSheets();
            XIndexAccess oSheetsIA = (XIndexAccess)oSheets;
            XSpreadsheet oSheet = (XSpreadsheet)oSheetsIA.getByIndex(0).Value;
            for (int i = 0; i < 10; i++)
            {
                for (int j = 0; j < 100; j++)
                {
                    XCell oCell = oSheet.getCellByPosition(i, j);
//add dummy values
                    //((XText)oCell).setString(((i+1) * (j+1)).ToString());//set strings
                    oCell.setValue((i + 1) * (j + 1));//or set doubles
                }
            }
            ((XStorable)oDoc).storeAsURL(fileName, propVals);//save document

            oDoc.dispose();
            oDoc = null;

        }


        /// <summary>
        ///                 * Read data from existing Calc document *
        /// </summary>
        public static void ReadExistingCalcRange()
        {
            //file name is with back slashes in the OOffice format only:
            string fileName = @"file:///C:/test.ods";
            string target = "A1:D999";
            //The first step is to use
            //the bootstrap method to start OpenOffice.org (or to access any existing instances):
            XComponentContext oStrap = uno.util.Bootstrap.bootstrap();
            //The next step is to use OpenOffice.org's service manager to create a desktop:
            XMultiServiceFactory oServMan = (XMultiServiceFactory)oStrap.getServiceManager();
            //Create loader component
            XComponentLoader oDesk = (XComponentLoader)oServMan.createInstance("com.sun.star.frame.Desktop");

            PropertyValue[] propVals = new PropertyValue[0];
            //And then an existing Calc document is added to the desktop:
            XComponent xDoc = oDesk.loadComponentFromURL(fileName, "_private:stream", 0, propVals);
            // Then use the service manager for current document
            XMultiServiceFactory xDocFactory = (XMultiServiceFactory)xDoc;
            // Get document sheets
            XSpreadsheets oSheets = ((XSpreadsheetDocument)xDoc).getSheets();
            // Create indexer
            XIndexAccess oSheetsIA = (XIndexAccess)oSheets;
            // Get first sheet
            XSpreadsheet oSheet = (XSpreadsheet)oSheetsIA.getByIndex(0).Value;
            // Get desired range
            XCellRange oRange = (XCellRange)oSheet.getCellRangeByName(target);
            // After this line there are few ways for the iteration through cells
            // see help docs here:
            //http://wiki.services.openoffice.org/wiki/Documentation/DevGuide/
            //I'm pretty sure there is an easier way to loop through cells
            //but here is my way to retrive rows and columns from address of range:
            int[] columns = GetColumnsFromString(target);
            int[] rows = GetRowsFromString(target);
            // (row and column indexes are starting from zero)
            int startcol = columns[0] - 1;
            int endcol = columns[1] - 1;
            int startrow = rows[0] - 1;
            int endrow = rows[1] - 1;
            ArrayList arr = new ArrayList();
            for (int r = startrow; r <= endrow; r++)
            {
                string[] line = new string[endcol - startcol + 1];
                for (int c = startcol; c <= endcol; c++)
                {
                    XCell oCell = (XCell)oRange.getCellByPosition(c, r);
                    line[c] = oCell.getFormula();
                }
                arr.Add(line);

            }
            xDoc.dispose();
            xDoc = null;
            // Display data
            foreach (string[] s in arr)
                Console.WriteLine("{0} | {1} | {2} | {3} |", s[0], s[1], s[2], s[3]);
            Console.Read();
        }
        /// <summary>
        ///     *   Get first and last column from range address *
        /// </summary>
        /// <param name="address"></param>
        /// <returns></returns>
        public static int[] GetColumnsFromString(string address)
        {
            int[] columns = new int[2];
            string sep = ":";
            string[] target = address.Split(sep.ToCharArray());
            string head = target[0];
            string tail = target[1];
            columns[0] = Col_AToI(CutNumeric(head));
            columns[1] = Col_AToI(CutNumeric(tail));
            return columns;
        }
        /// <summary>
        ///      *   Get first and last row from range address *
        /// </summary>
        /// <param name="address"></param>
        /// <returns></returns>
        public static int[] GetRowsFromString(string address)
        {
            int[] rows = new int[2];
            string sep = ":";
            string[] target = address.Split(sep.ToCharArray());
            string head = target[0];
            string tail = target[1];
            rows[0] = int.Parse(CutAlpha(head));
            rows[1] = int.Parse(CutAlpha(tail));
            return rows;
        }

        public static string CutNumeric(string str)
        {
            try
            {
                string pattern = @"[0-9]";
                Regex reg = new Regex(pattern, RegexOptions.IgnoreCase);
                str = reg.Replace(str, "");
                return str;
            }
            catch (System.Exception ex)
            {
                throw ex;
            }
        }
        public static string CutAlpha(string str)
        {
            try
            {
                string pattern = @"[aA-zZ]";
                Regex reg = new Regex(pattern, RegexOptions.IgnoreCase);
                str = reg.Replace(str, "");
                return str;
            }
            catch (System.Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        ///           * Change column letter(s) to integer *
        /// </summary>
        /// from http://www.codekeep.net/snippets/63b58dcb-ab47-4a75-8016-e771fad706c6.aspx
        /// <param name="strColumn"></param>
        /// <returns></returns>
        public static int Col_AToI(string strColumn)
        {
            strColumn = strColumn.ToUpper();

            if (strColumn.Length == 1)
            {
                return Convert.ToByte(Convert.ToChar(strColumn)) - 64;
            }
            else if (strColumn.Length == 2)
            {
                return
                    ((Convert.ToByte(strColumn[0]) - 64) * 26) +
                    (Convert.ToByte(strColumn[1]) - 64);

            }
            else if (strColumn.Length == 3)
            {
                return
                    ((Convert.ToByte(strColumn[0]) - 64) * 26 * 26) +
                    ((Convert.ToByte(strColumn[1]) - 64) * 26) +
                    (Convert.ToByte(strColumn[2]) - 64);
            }
            else
            {
                throw new ApplicationException("Column Length must be between 1 and 3.");
            }
        }
    }
}
Title: Re: .NET MISCELLANEOUS/GENERAL Routines
Post by: gile on March 06, 2010, 11:31:30 am
Getting or Setting Xrecord to a dictionary (or extension dictionary)

Code: [Select]
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;
using acadApp = Autodesk.AutoCAD.ApplicationServices.Application;

namespace Dictionaries
{
    public class DictSample
    {
        // SetXrecord (overloaded)
        public void SetXrecord(Entity ent, string key, ResultBuffer resbuf)
        {
            Document doc = acadApp.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            using (Transaction tr = db.TransactionManager.StartTransaction())
            {
                ent.UpgradeOpen();
                ent.CreateExtensionDictionary();
                DBDictionary xDict = (DBDictionary)tr.GetObject(ent.ExtensionDictionary, OpenMode.ForWrite);
                Xrecord xRec = new Xrecord();
                xRec.Data = resbuf;
                xDict.SetAt(key, xRec);
                tr.AddNewlyCreatedDBObject(xRec, true);
                tr.Commit();
            }
        }

        public void SetXrecord(DBDictionary dict, string key, ResultBuffer resbuf)
        {
            Document doc = acadApp.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            using (Transaction tr = db.TransactionManager.StartTransaction())
            {
                dict.UpgradeOpen();
                Xrecord xRec = new Xrecord();
                xRec.Data = resbuf;
                dict.SetAt(key, xRec);
                tr.AddNewlyCreatedDBObject(xRec, true);
                tr.Commit();
            }
        }

        public void SetXrecord(string dictName, string key, ResultBuffer resbuf)
        {
            Document doc = acadApp.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            using (Transaction tr = db.TransactionManager.StartTransaction())
            {
                DBDictionary NOD = (DBDictionary)tr.GetObject(db.NamedObjectsDictionaryId, OpenMode.ForWrite);
                DBDictionary dict;
                try
                {
                    dict = tr.GetObject(NOD.GetAt(dictName), OpenMode.ForWrite) as DBDictionary;
                }
                catch
                {
                    dict = new DBDictionary();
                    NOD.SetAt(dictName, dict);
                    tr.AddNewlyCreatedDBObject(dict, true);
                    dict.UpgradeOpen();
                }
                Xrecord xRec = new Xrecord();
                xRec.Data = resbuf;
                dict.SetAt(key, xRec);
                tr.AddNewlyCreatedDBObject(xRec, true);
                tr.Commit();
            }
        }

        public void SetXrecord(ObjectId id, string key, ResultBuffer resbuf)
        {
            Document doc = acadApp.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            using (Transaction tr = db.TransactionManager.StartTransaction())
            {
                Entity ent = tr.GetObject(id, OpenMode.ForRead) as Entity;
                if (ent != null)
                {
                    ent.UpgradeOpen();
                    ent.CreateExtensionDictionary();
                    DBDictionary xDict = (DBDictionary)tr.GetObject(ent.ExtensionDictionary, OpenMode.ForWrite);
                    Xrecord xRec = new Xrecord();
                    xRec.Data = resbuf;
                    xDict.SetAt(key, xRec);
                    tr.AddNewlyCreatedDBObject(xRec, true);
                }
                else
                {
                    DBDictionary dict = tr.GetObject(id, OpenMode.ForRead) as DBDictionary;
                    if (dict != null)
                    {
                        dict.UpgradeOpen();
                        Xrecord xRec = new Xrecord();
                        xRec.Data = resbuf;
                        dict.SetAt(key, xRec);
                        tr.AddNewlyCreatedDBObject(xRec, true);
                    }
                }
                tr.Commit();
            }
        }

        // GetXrecord (overloaded)
        public ResultBuffer GetXrecord(Entity ent, string key)
        {
            Document doc = acadApp.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            using (Transaction tr = db.TransactionManager.StartTransaction())
            {
                try
                {
                    DBDictionary xDict =
                        (DBDictionary)tr.GetObject(ent.ExtensionDictionary, OpenMode.ForRead, false);
                    Xrecord xRec = (Xrecord)tr.GetObject(xDict.GetAt(key), OpenMode.ForRead, false);
                    return xRec.Data;
                }
                catch
                {
                    return null;
                }
            }
        }

        public ResultBuffer GetXrecord(DBDictionary dict, string key)
        {
            Document doc = acadApp.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            using (Transaction tr = db.TransactionManager.StartTransaction())
            {
                try
                {
                    Xrecord xRec = (Xrecord)tr.GetObject(dict.GetAt(key), OpenMode.ForRead, false);
                    return xRec.Data;
                }
                catch
                {
                    return null;
                }
            }
        }

        public ResultBuffer GetXrecord(string dictName, string key)
        {
            Document doc = acadApp.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            using (Transaction tr = db.TransactionManager.StartTransaction())
            {
                try
                {
                    DBDictionary NOD = (DBDictionary)tr.GetObject(db.NamedObjectsDictionaryId, OpenMode.ForRead);
                    DBDictionary dict = (DBDictionary)tr.GetObject(NOD.GetAt(dictName), OpenMode.ForRead, false);
                    Xrecord xRec = (Xrecord)tr.GetObject(dict.GetAt(key), OpenMode.ForRead, false);
                    return xRec.Data;
                }
                catch
                {
                    return null;
                }
            }
        }

        public ResultBuffer GetXrecord(ObjectId id, string key)
        {
            Document doc = acadApp.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            using (Transaction tr = db.TransactionManager.StartTransaction())
             {
                Xrecord xRec = new Xrecord();
                Entity ent = tr.GetObject(id, OpenMode.ForRead, false) as Entity;
                if (ent != null)
                {
                    try
                    {
                        DBDictionary xDict = (DBDictionary)tr.GetObject(ent.ExtensionDictionary, OpenMode.ForRead, false);
                        xRec = (Xrecord)tr.GetObject(xDict.GetAt(key), OpenMode.ForRead, false);
                        return xRec.Data;
                    }
                    catch
                    {
                        return null;
                    }
                }
                else
                {
                    DBDictionary dict = tr.GetObject(id, OpenMode.ForRead, false) as DBDictionary;
                    if (dict != null)
                    {
                        try
                        {
                            xRec = (Xrecord)tr.GetObject(dict.GetAt(key), OpenMode.ForRead, false);
                            return xRec.Data;
                        }
                        catch
                        {
                            return null;
                        }
                    }
                    else
                        return null;
                }
            }
        }
    }
}
Title: Re: .NET MISCELLANEOUS/GENERAL Routines
Post by: fixo on March 11, 2010, 03:19:14 am
Automation Word using late-binding and interaction with AutoCAD
Oops...
I have removed my message by reason of bad code block
Try substituted code instead  :oops:

Create project 'WordReflection'
Drop on form 'Form1' DataGridView named 'dataGridView1'
Drop on form two buttons named 'button1' and 'button2'
Add text for button1 - "Select Circles"
Add text for button2 - "Export DataGridView To Word Document"
Unzip files from an attached archive and add to the project
Change file name and text for footer inside the code block for 'button2'
Compile project
Draw a several circles then run program

Hope that would helps to somebody from our community

~'J'~
Title: Re: .NET MISCELLANEOUS/GENERAL Routines
Post by: Ken Alexander on March 11, 2010, 11:43:20 am
Read / Write Excel examples
(it is necessary to change the file name in the code)

===  VB.NET  ===

When working with a large amount of data, you might use Range.Value; much, much quicker.

Code: [Select]
Dim objCells As Range = objSheet.Range(objSheet.Cells(1, 1), objSheet.Cells(101, 3))
Dim Values(101, 3) As String

For i = 0 To 100
     For j = 0 To 2
          Values(i, j) = Rnd(5).ToString
     Next
Next

'add the entire array at once.
objCells.Value = Values

Title: Re: .NET MISCELLANEOUS/GENERAL Routines
Post by: fixo on March 11, 2010, 12:10:51 pm
Read / Write Excel examples
(it is necessary to change the file name in the code)

===  VB.NET  ===

When working with a large amount of data, you might use Range.Value; much, much quicker.

Code: [Select]
Dim objCells As Range = objSheet.Range(objSheet.Cells(1, 1), objSheet.Cells(101, 3))
Dim Values(101, 3) As String

For i = 0 To 100
     For j = 0 To 2
          Values(i, j) = Rnd(5).ToString
     Next
Next

'add the entire array at once.
objCells.Value = Values


Feel free to upload your own example here

~'J'~
Title: Re: .NET MISCELLANEOUS/GENERAL Routines
Post by: Ken Alexander on March 11, 2010, 03:30:57 pm
Quote

Feel free to upload your own example here

~'J'~


Code: [Select]
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim objExcel As Excel.Application = Nothing
        Dim objBooks As Workbooks = Nothing
        Dim objBook As Workbook = Nothing
        Dim objSheets As Sheets = Nothing
        Dim objSheet As Worksheet = Nothing
        Dim objCells As Range = Nothing
        Dim LstColumns() As String = Nothing

        Dim NumberOfRows As Integer = 100
        Dim NumberOfColumns As Integer = 3

        Dim PopulateValues(NumberOfRows, NumberOfColumns) As String
        Dim ReadValues(NumberOfRows, NumberOfColumns) As Object

        Try
            objExcel = New Excel.Application
            objExcel.Visible = True
            objBooks = objExcel.Workbooks
            objBook = objBooks.Add()
            objBook.Activate()
            objSheets = objBook.Sheets
            objSheet = objSheets.Item(1)
            objSheet.Cells.ClearContents()
            objCells = objSheet.Range(objSheet.Cells(1, 1), objSheet.Cells(NumberOfRows, NumberOfColumns))

            For iRow = 0 To NumberOfRows - 1
                For iColumn = 0 To NumberOfColumns - 1
                    PopulateValues(iRow, iColumn) = "Row:" & (iRow + 1).ToString & " Column:" & (iColumn + 1).ToString
                Next
            Next

            'populate entire array (very fast)
            objCells.Value = PopulateValues
            objCells.Columns.AutoFit()
            objBook.SaveAs("C:\SampleReadWriteData.xls", Excel.XlFileFormat.xlWorkbookNormal)
            objBook.Close()


            objBook = objBooks.Open("C:\SampleReadWriteData.xls")
            objBook.Activate()
            objSheets = objBook.Sheets
            objSheet = objSheets.Item(1)
            objCells = objSheet.Range(objSheet.Cells(1, 1), objSheet.Cells(NumberOfRows, NumberOfColumns))

            'populate entire array (very fast)
            ReadValues = objCells.Value

            Me.ListView1.Clear()
            Me.ListView1.View = View.Details
            Me.ListView1.GridLines = True
            Me.ListView1.FullRowSelect = True

            LstColumns = New String() {"X coordinate", "Y coordinate", "Z coordinate"}
            For Each ColHeaderText As String In LstColumns
                Me.ListView1.Columns.Add(ColHeaderText, 96, HorizontalAlignment.Left)
            Next

            For iRow As Integer = 1 To NumberOfRows
                Dim lvi As New ListViewItem(ReadValues(iRow, 1).ToString, 0)
                For iColumn As Integer = 2 To NumberOfColumns
                    lvi.SubItems.Add(ReadValues(iRow, iColumn).ToString)
                Next
                Me.ListView1.Items.Add(lvi)
            Next

            Me.ListView1.AutoResizeColumns(ColumnHeaderAutoResizeStyle.ColumnContent)

            objBook.Close()
            objExcel.Quit()
        Catch ex As Exception
            MessageBox.Show(ex.StackTrace)
        Finally
            System.Runtime.InteropServices.Marshal.FinalReleaseComObject(objExcel)
        End Try
    End Sub
Title: Re: .NET MISCELLANEOUS/GENERAL Routines
Post by: fixo on March 12, 2010, 12:02:42 pm
Thanks,

Keep  sharing :)

Regards,

~'J'~
Title: Re: .NET MISCELLANEOUS/GENERAL Routines
Post by: HasanCAD on March 17, 2010, 09:03:43 am
Hi all

Its first time I visit .NET
The question is
How to load this code?

Regards
Title: Re: .NET MISCELLANEOUS/GENERAL Routines
Post by: fixo on March 18, 2010, 09:02:21 am
Hi all

Its first time I visit .NET
The question is
How to load this code?

Regards


See post#1:

LIBRARY THREAD for  AutoCAD MISCELLANEOUS/GENERAL
 Members are encouraged to post any functions, methods, snips regarding
AutoCAD MISCELLANEOUS/GENERAL in .NET : C# ,  VB , F# , Python , etc

Feel free to include comments, descriptive notes, limitations,  and images to document your post.

Please post questions in a regular thread. :x
Title: Re: .NET MISCELLANEOUS/GENERAL Routines
Post by: fixo on March 18, 2010, 09:26:39 am
Quick way to create HTML report
Code: [Select]

Create Class library project  BlockReport
Add 2 classes: Report.cs and SelectBlocks.cs

//
// code for Report.cs
//

using System;
using System.Collections.Generic;
using System.Text;
using Autodesk.AutoCAD.Runtime;
using System.Diagnostics;
using System.Data;
using System.IO;
using System.Windows.Forms;
using System.ComponentModel;

[assembly: CommandClass(typeof(BlockReport.Report))]

namespace BlockReport
{
    public class Report
    {
        System.Data.DataTable tbl;
        string tblname = "BLOCK INFO";
        string filename = @"C:\BLOCKS.html";//<--change path for outputfile here



        [CommandMethod("REPORT")]
        public void Doit()
        {
            tbl = SelectBlocks.BlockInfoToTable();

            DataView dv = tbl.DefaultView;

            dv.Sort = "Name ASC";

            tbl = dv.ToTable();

            BuildHTMLDoc(tbl, tblname, filename);
            Process.Start(filename);
        }

        public void BuildHTMLDoc(System.Data.DataTable dtb, string tblname, string filename)
        {
            string bdcol = "#91b6dd";
            string fcol1 = "#33066";
            string fcol2 = "#3300CC";
            string bcol1 = "#e8e8e8";
            string bcol2 = "#c8c8c8";
            string fcolor = "";
            string bcolor = "";

            //possible HTML colors (a bit of):
            //6799ff royal blue
            //d7b941 dirty yellow
            //3366cc blue
            //ededed light gray 25
            //e0e0e0 light gray 50
            //ff0000 red
            //666699 violet
            //cc3333 indian red
            //3c5b00 green
            //73ad00 light green
            //d0d5c6 light khaki
            //91b6dd light steel blue

            try
            {
                DateTime dt = DateTime.Now;
                string dat = dt.ToString("d");
                string textHTML =
                    SetDocumentStart("Simple Report Example") +
                    SetBodyStart(bdcol) +
                    SetParagraphStartLeft(dat, fcol1) +
                    SetCaption(dat, fcol1) +
                    SetTitle("2", "Report Title") +
                    SetTitle("3", tblname) +
                    SetParagraphStart() +
                    SetTableStart("50");//<--table width in percents
                StringBuilder sb = new StringBuilder();
                sb.Append(textHTML);
                textHTML = SetRowStart(bcolor);
                sb.Append(textHTML);
                int cnt = 0;

                for (int j = 0; j < dtb.Columns.Count; j++)
                {

                    textHTML = SetCellStart(dtb.Columns[j].ColumnName, "blue");
                    sb.Append(textHTML);
                    textHTML = SetCellEnd();
                    sb.Append(textHTML);
                    cnt += 1;
                }
                textHTML = SetRowEnd();
                sb.Append(textHTML);
                cnt = 0;

                for (int i = 0; i < dtb.Rows.Count; i++)
                {

                    if (i % 2 == 0)
                    {
                        bcolor = bcol1;
                        fcolor = fcol1;
                    }
                    else
                    {
                        bcolor = bcol2;
                        fcolor = fcol2;
                    }
                    textHTML = SetRowStart(bcolor);
                    sb.Append(textHTML);
                    DataRow dr = dtb.Rows[i];
                    object[] line = dr.ItemArray;

                    for (int j = 0; j < dtb.Columns.Count; j++)
                    {
                        string celltext = "";
                        object cellvalue = line[j];

                        if (cellvalue == null)
                        {
                            celltext = "--";
                        }
                        else
                        {
                            celltext = cellvalue.ToString();
                        }


                        textHTML = SetCellStart(celltext, fcolor);
                        sb.Append(textHTML);
                        textHTML = SetCellEnd();
                        sb.Append(textHTML);
                        cnt += 1;
                    }
                    textHTML = SetRowEnd();
                    sb.Append(textHTML);
                }
               
                textHTML = SetRowStart(bcol1);
                sb.Append(textHTML);
                for (int j = 0; j < dtb.Columns.Count - 2; j++)
                {
                    string celltext = "";
                    textHTML = SetCellStart(celltext, fcolor);
                    sb.Append(textHTML);
                    textHTML = SetCellEnd();
                    sb.Append(textHTML);
                    cnt += 1;
                }
               
                textHTML = SetCellStart("Blocks Count: ", fcolor);
                sb.Append(textHTML);
                textHTML = SetCellEnd();
                sb.Append(textHTML);

                System.Data.DataColumn count =
                    new System.Data.DataColumn("Count",
                    System.Type.GetType("System.Int16"));
                count.Expression = "COUNT(Name)";
                dtb.Columns.Add(count);


                string num = dtb.Rows[0].ItemArray[dtb.Columns.Count-1].ToString();

                textHTML = SetCellStart(num, fcolor);
                sb.Append(textHTML);
                textHTML = SetCellEnd();
                sb.Append(textHTML);
                textHTML = SetRowEnd();
                sb.Append(textHTML);
                //
                textHTML = SetTableEnd();
                sb.Append(textHTML);
                textHTML = SetParagraphEnd();
                sb.Append(textHTML);
                textHTML = SetBodyEnd();
                sb.Append(textHTML);
                textHTML = SetDocumentEnd();
                sb.Append(textHTML);
                using (StreamWriter sw = new StreamWriter(filename))
                {
                    sw.Write(sb.ToString());
                }
            }
            catch (System.Exception ex)
            {
                MessageBox.Show(ex.Message + "\n" + ex.StackTrace);
            }

        }
        private string SetDocumentStart(string head)
        {
            return "<html><head><title><" + head + ">" + "</title></head>";
        }
        private string SetDocumentEnd()
        {
            return "</html>";
        }
        private string SetBodyStart(string color)
        {
            return "<body><body bgcolor =" + "" + color + "" + " " + Environment.NewLine;
        }
        private string SetBodyEnd()
        {
            return "</body bgcolor></body>" + Environment.NewLine;
        }
        private string SetTitle(string size, string value)
        {
            return "<h" + size + "><p align=center>" + value + "</p align></h" + size + ">";
        }
        private string SetParagraphIndent(string value, string color)
        {
            return "<p><blockquote><font color=" + "" + color + "" + " " + value + "</font><blockquote></p>";
        }
        private string SetParagraphStart()
        {
            return "<p><p align=center>";
        }
        private string SetParagraphStartLeft(string value, string color)
        {
            return "<p><p align=left><font color=" + "" + color + "" + " " + value + "</font></p>";
        }
        private string SetParagraphEnd()
        {
            return "<p><p align=center>" + Environment.NewLine;
        }
        private string SetTableStart(string width)
        {
            return "<table width=" + "" + width + "%%" + "" + "><t align=center>";
        }
        private string SetTableEnd()
        {
            return "<t align></table>" + Environment.NewLine;
        }
        private string SetRowStart(string color)
        {
            return "<tr><tr align=center><tr bgcolor=" + "" + color + "" + ">";
        }
        private string SetRowEnd()
        {
            return "</tr align></tr>" + Environment.NewLine;
        }
        private string SetCellStart(string value, string color)
        {
            string cell = "<td><td align=center><font color=" + "" + color + "" + ">" + value + "</font></td align></td>";
            return cell;
        }
        private string SetCellEnd()
        {
            return "</td align></td>" + Environment.NewLine;
        }

        private string SetCaption(string caption, string color)
        {
            return "<caption><font color=" + "" + color + "" + ">" + "<b>" + caption + "</b></font></caption>";
        }

    }
}



//
// code for SelectBlocks.cs
//
using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.IO;
using System.Threading;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.GraphicsInterface;
using Autodesk.AutoCAD.DatabaseServices;
using AcDb = Autodesk.AutoCAD.DatabaseServices;
using acadApp = Autodesk.AutoCAD.ApplicationServices.Application;
using Autodesk.AutoCAD.ApplicationServices;
using System.Windows.Forms;

[assembly: CommandClass(typeof(BlockReport.SelectBlocks))]

namespace BlockReport
{
    public class SelectBlocks
    {

        /// <summary>
        ///
        /// </summary>
        /// <returns></returns>
        static public System.Data.DataTable BlockInfoToTable()
        {
            System.Data.DataTable dt = new System.Data.DataTable();
            try
            {

                Document doc = acadApp.DocumentManager.MdiActiveDocument;
                Database db = HostApplicationServices.WorkingDatabase;
                Editor ed = doc.Editor;
                Transaction tr = db.TransactionManager.StartTransaction();
                using (tr)
                {
                    /*blocks just with attributes
//                    TypedValue[] tvs = new TypedValue[]
//{ new TypedValue((int)DxfCode.Start, "INSERT"),
//       new TypedValue((int)DxfCode.HasSubentities, 1)
//                    };*/
                    TypedValue[] tvs = new TypedValue[]
{ new TypedValue((int)DxfCode.Start, "INSERT")};

                    SelectionFilter sf = new SelectionFilter(tvs);

                    PromptSelectionResult psr = ed.SelectAll(sf);

                    SelectionSet sset = psr.Value;

                    MessageBox.Show(sset.Count.ToString());

                    dt.Columns.AddRange(new System.Data.DataColumn[]{
            new System.Data.DataColumn("Name",System.Type.GetType("System.String")),
new System.Data.DataColumn("ObjectID",System.Type.GetType("System.String")),
             new System.Data.DataColumn("X_Coordinate",System.Type.GetType("System.Double")),
              new System.Data.DataColumn("Y_Coordinate",System.Type.GetType("System.Double")),
               new System.Data.DataColumn("Z_Coordinate",System.Type.GetType("System.Double")),
                new System.Data.DataColumn("Rotation",System.Type.GetType("System.Double")),
               });

                    foreach (SelectedObject sobj in sset)
                    {
                        DBObject dbobj = tr.GetObject(sobj.ObjectId, OpenMode.ForRead);
                        BlockReference bref = dbobj as BlockReference;


                        object[] param = new object[6];
                        if (bref != null)
                        {                           
                            param[0] = EffectiveName(bref);
                            param[1] = sobj.ObjectId;
                            param[2] = Math.Round(bref.Position.X, 3);
                            param[3] = Math.Round(bref.Position.Y, 3);
                            param[4] = Math.Round(bref.Position.Z, 3);
                            param[5] = Math.Round(RadianToDegree(bref.Rotation), 3);

                            DataRow dr = dt.NewRow();
                            dr.ItemArray = param;
                            dt.Rows.Add(dr);
                        }
                    }
                }
            }
            catch (System.Exception ex)
            {
                MessageBox.Show(ex.StackTrace);
            }
            return dt;

        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="blkref"></param>
        /// <returns></returns>
        static public string EffectiveName(BlockReference blkref)
        {
            if (blkref.IsDynamicBlock)
            {
                using (BlockTableRecord obj = (BlockTableRecord)
                blkref.DynamicBlockTableRecord.GetObject(OpenMode.ForRead))
                    return obj.Name;
            }
            return blkref.Name;
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="angle"></param>
        /// <returns></returns>
        public static double RadianToDegree(double angle)
        {
            return angle * (180.0 / Math.PI);
        }

    }
}




~'J'~
Title: Re: .NET MISCELLANEOUS/GENERAL Routines
Post by: fixo on March 21, 2010, 08:43:27 am
Export Excel sheet into the Acad table
Tested on Excel2007 only

~'J'~
Title: Re: .NET MISCELLANEOUS/GENERAL Routines
Post by: fixo on March 28, 2010, 06:12:07 am
Editing the alpha-numeric text(s) / mtext(s)

~'J'~

Oops, wrong thread
Moved in there:

http://www.theswamp.org/index.php?topic=31860.0
Title: Re: .NET MISCELLANEOUS/GENERAL Routines
Post by: gile on June 06, 2010, 06:56:13 pm
A little Matrix class for general matrix calculus (not exclusively 2d or 3d transformation matrices).
I's quite small but maybe will grow...

Code: [Select]
using System;

namespace MatrixSample
{
    public class Matrix
    {
        // fields
        private int m_numRows;
        private int m_numColumns;
        private double[,] m_matArray;

        // Constructors
        public Matrix(double[,] matArray)
        {
            m_matArray = matArray;
            m_numRows = matArray.GetLength(0);
            m_numColumns = matArray.GetLength(1);
        }

        public Matrix(int numRows, int numColumns)
        {
            m_numRows = numRows;
            m_numColumns = numColumns;
            m_matArray = new double[numRows, numColumns];
        }

        // Indexor
        public double this[int i, int j]
        {
            get { return m_matArray[i, j]; }
            set { m_matArray[i, j] = value; }
        }

        // Properties
        public bool IsSquare
        {
            get { return m_numColumns == m_numRows; }
        }

        public int NumColumns
        {
            get { return m_numColumns; }
        }

        public int NumRows
        {
            get { return m_numRows; }
        }

        // Static method
        public static Matrix Identity(int dim)
        {
            Matrix result = new Matrix(dim, dim);
            for (int i = 0; i < dim; i++)
            {
                double[] row = new double[dim];
                for (int j = 0; j < dim; j++)
                {
                    row[j] = i == j ? 1.0 : 0.0;
                }
                result.SetRowAt(i, row);
            }
            return result;
        }

        // Instance methods
        public Matrix GaussJordan(Matrix mat)
        {
            if (!this.IsSquare)
                throw new MatrixException("First matrix is not square");
            mat = this.Merge(mat);
            int numRows = mat.NumRows;
            int numColumns = mat.NumColumns;
            for (int rowIndex = 0; rowIndex < numRows; rowIndex++)
            {
                double pivot = 0.0;
                int pivotRowIndex = mat.GetPivotRow(rowIndex, ref pivot);
                if (pivot == 0.0)
                    return null;
                double[] pivotRow;
                mat.PermuteAt(pivotRowIndex, rowIndex, out pivotRow);
                pivotRow = Array.ConvertAll<double, double>(pivotRow, x => x / pivot);
                mat.SetRowAt(rowIndex, pivotRow);
                for (int i = 0; i < numRows; i++)
                {
                    if (i == rowIndex)
                        continue;
                    double first = mat[i, 0];
                    for (int j = 0; j < numColumns; j++)
                    {
                        mat[i, j] -= first * pivotRow[j];
                    }
                }
                mat = mat.RemoveFirstColumn();
                numColumns--;
            }
            return mat;
        }

        private Matrix RemoveFirstColumn()
        {
            Matrix result = new Matrix(this.m_numRows, this.m_numColumns - 1);
            for (int i = 0; i < this.m_numRows; i++)
            {
                for (int j = 0; j < this.m_numColumns - 1; j++)
                {
                    result[i, j] = this[i, j + 1];
                }
            }
            return result;
        }

        private void PermuteAt(int pivotRowIndex, int rowIndex, out double[] pivotRow)
        {
            pivotRow = this.GetRowAt(pivotRowIndex);
            for (int i = pivotRowIndex; i > rowIndex; i--)
            {
                this.SetRowAt(i, this.GetRowAt(i - 1));
            }
            this.SetRowAt(rowIndex, pivotRow);
        }

        private int GetPivotRow(int index, ref double pivot)
        {
            int result = 0;
            for (int i = index; i < this.NumRows; i++)
            {
                double p = (this.GetRowAt(i))[0];
                if (Math.Abs(p) > Math.Abs(pivot))
                {
                    pivot = p;
                    result = i;
                }
            }
            return result;
        }

        public Matrix Merge(Matrix mat)
        {
            if (this.NumRows != mat.NumRows)
                throw new MatrixException("Different number of rows");
            Matrix result = new Matrix(this.NumRows, this.NumColumns + mat.NumColumns);
            for (int i = 0; i < this.NumRows; i++)
            {
                double[] row = new double[this.NumColumns + mat.NumColumns]; ;
                this.GetRowAt(i).CopyTo(row, 0);
                mat.GetRowAt(i).CopyTo(row, this.NumColumns);
                result.SetRowAt(i, row);
            }
            return result;
        }

        public Matrix Inverse()
        {
            if (!this.IsSquare)
                throw new MatrixException("First matrix is not square");
            return this.GaussJordan(Identity(this.NumRows));
        }

        public double[] GetColumnAt(int index)
        {
            if (index >= m_numColumns)
                throw new IndexOutOfRangeException();
            double[] result = new double[m_numRows];
            for (int i = 0; i < m_numRows; i++)
            {
                result[i] = m_matArray[i, index];
            }
            return result;
        }

        public double[] GetRowAt(int index)
        {
            if (index >= m_numRows)
                throw new IndexOutOfRangeException();
            double[] result = new double[m_numColumns];
            for (int i = 0; i < m_numColumns; i++)
            {
                result[i] = m_matArray[index, i];
            }
            return result;
        }

        public void SetColumnAt(int index, double[] column)
        {
            if (index >= m_numColumns)
                throw new IndexOutOfRangeException();
            if (column.Length != m_numRows)
                throw new MatrixException("Array length is not valid");
            double[] result = new double[m_numRows];
            for (int i = 0; i < m_numRows; i++)
            {
                m_matArray[index, i] = column[i];
            }
        }

        public void SetRowAt(int index, double[] row)
        {
            if (index >= m_numRows)
                throw new IndexOutOfRangeException();
            if (row.Length != m_numColumns)
                throw new MatrixException("Array length is not valid");
            double[] result = new double[m_numColumns];
            for (int i = 0; i < m_numColumns; i++)
            {
                m_matArray[index, i] = row[i];
            }
        }

        public Matrix Transpose()
        {
            Matrix result = new Matrix(m_numColumns, m_numRows);
            for (int i = 0; i < m_numColumns; i++)
            {
                result.SetRowAt(i, this.GetColumnAt(i));
            }
            return result;
        }
    }

    class MatrixException : Exception
    {
        public MatrixException(string msg)
            : base(msg)
        {
        }
    }
}

Title: Re: .NET MISCELLANEOUS/GENERAL Routines
Post by: jgr on August 20, 2010, 11:46:12 am
Reading a CTB file

CTB file it is a file that contains compressed text with zlib
www.zlib.net (http://www.zlib.net)

File format:

First 52 bytes = header (not compressed, like PIAFILEVERSION_2.0,CTBVER1,compress)
next 4 bytes (UInteger) = decompressed stream size
next 4 bytes (UInteger) = compressed stream size
after this = compressed data

The code in CTBReader.rar (vb.net) is commented, but in spanish (sorry i do not speack english)

The example uses (C# code included) a managed version of zlib , free and open Source:
http://www.componentace.com/zlib_.NET.htm

I do not understand all the uncompressed data, such as color, but ....
Title: Re: .NET MISCELLANEOUS/GENERAL Routines
Post by: Jeff H on August 23, 2010, 07:14:27 am
**************************EDIT****************************************
Need to wrap side database in a using statement also
**************************EDIT****************************************

Here are 4 methods Basiclly are set up for having external drawings storing info and grabbing it.
The first two are plotsettings "PageSetup"  one is for filling a combobox or you get a list plotsettings and the second wblockclones it from the closed drawing by the name of the first functions

The second two are same but for textstyles and this just adds the text styles. Let me know if you have a problem with texthieght of your styles there is a issue but can be eaisly worked around and width factor does not persist and also eaisly be fixed. I am not talking about the code posted There is a issuse with the API that will use the Database TextSize instead

I have other routines but these were the first I saw going through a file, also if you would C# it would give me some practice
Also obviously this code is set up more for use from pallette whatever so you will probably need do handle document Locking

Code: [Select]
Public Function GetPlotSettinsList(ByVal PlotSettingsFile As String) As List(Of String)
            Dim PlotSettinsList As New List(Of String)
            Dim CurrentDatabase As Database = HostApplicationServices.WorkingDatabase
            Dim SourceDatabase As New Database(False, True)
            SourceDatabase.ReadDwgFile(PlotSettingsFile, FileOpenMode.OpenForReadAndAllShare, True, "")
            Using currentTransaction As Transaction = CurrentDatabase.TransactionManager.StartTransaction
                Using sourceTransaction As Transaction = SourceDatabase.TransactionManager.StartTransaction
                    Dim sourcePlotDic As DBDictionary = SourceDatabase.PlotSettingsDictionaryId.GetObject(OpenMode.ForRead)
                    For Each dit As DictionaryEntry In sourcePlotDic
                        PlotSettinsList.Add(dit.Key.ToString)
                    Next
                    currentTransaction.Commit()
                End Using
            End Using
            Return PlotSettinsList
        End Function

        Public Sub AddPlotSettings(ByVal PlotSettingsFile As String, ByVal PlotSettingsName As String)
            Dim CurrentDatabase As Database = HostApplicationServices.WorkingDatabase
            Dim SourceDatabase As New Database(False, True)
            SourceDatabase.ReadDwgFile(PlotSettingsFile, FileOpenMode.OpenForReadAndAllShare, True, "")
            Using currentTransaction As Transaction = CurrentDatabase.TransactionManager.StartTransaction
                Using sourceTransaction As Transaction = SourceDatabase.TransactionManager.StartTransaction
                    Dim sourcePlotDic As DBDictionary = SourceDatabase.PlotSettingsDictionaryId.GetObject(OpenMode.ForRead)
                    If sourcePlotDic.Contains(PlotSettingsName) Then
                        Dim objID As ObjectId = sourcePlotDic.GetAt(PlotSettingsName)
                        Dim pl As PlotSettings = objID.GetObject(OpenMode.ForRead)
                        Dim cpl As New PlotSettings(False)
                        cpl.CopyFrom(pl)
                        cpl.AddToPlotSettingsDictionary(CurrentDatabase)
                        Dim bt As BlockTable = CurrentDatabase.BlockTableId.GetObject(OpenMode.ForRead)
                        Dim btr As BlockTableRecord = bt(BlockTableRecord.PaperSpace).GetObject(OpenMode.ForRead)
                        Dim lytobjID As ObjectId = btr.LayoutId.GetObject(OpenMode.ForRead).ObjectId
                        Dim lytps As PlotSettings = lytobjID.GetObject(OpenMode.ForWrite)
                        lytps.CopyFrom(cpl)
                    End If
                    currentTransaction.Commit()
                End Using
            End Using
        End Sub


        Public Function GetTextStyleList(ByVal TextStyleFile As String) As List(Of String)
            Dim textStyleList As New List(Of String)
            Dim CurrentDatabase As Database = HostApplicationServices.WorkingDatabase
            Dim SourceDatabase As New Database(False, True)
            SourceDatabase.ReadDwgFile(TextStyleFile, FileOpenMode.OpenForReadAndAllShare, True, "")
            Using currentTransaction As Transaction = CurrentDatabase.TransactionManager.StartTransaction
                Using sourceTransaction As Transaction = SourceDatabase.TransactionManager.StartTransaction
                    Dim sourceTextStyleTbl As TextStyleTable = SourceDatabase.TextStyleTableId.GetObject(OpenMode.ForRead)
                    For Each sourceTextStyleTblRecID As ObjectId In sourceTextStyleTbl
                        Dim sourceTextStyleTblRec As TextStyleTableRecord = sourceTextStyleTblRecID.GetObject(OpenMode.ForRead)
                        textStyleList.Add(sourceTextStyleTblRec.Name)
                    Next
                    currentTransaction.Commit()
                End Using
            End Using
            Return textStyleList
        End Function

        Public Function AddTextStyle(ByVal textStyleFile As String, ByVal textStyleName As String) As ObjectId
            Dim CurrentDatabase As Database = HostApplicationServices.WorkingDatabase
            Dim SourceDatabase As New Database(False, True)
            SourceDatabase.ReadDwgFile(textStyleFile, FileOpenMode.OpenForReadAndAllShare, True, "")
            Using currentTransaction As Transaction = CurrentDatabase.TransactionManager.StartTransaction
                Using sourceTransaction As Transaction = SourceDatabase.TransactionManager.StartTransaction
                    Dim CurrentTextStyleTbl As TextStyleTable = CurrentDatabase.TextStyleTableId.GetObject(OpenMode.ForWrite)
                    Dim sourceTextStyleTbl As TextStyleTable = SourceDatabase.TextStyleTableId.GetObject(OpenMode.ForRead)
                    If Not sourceTextStyleTbl.Has(textStyleName) Then Return Nothing
                    Dim sourceTextStyleTblRec As TextStyleTableRecord = sourceTextStyleTbl(textStyleName).GetObject(OpenMode.ForRead)
                    Dim map As New DatabaseServices.IdMapping
                    Dim sourceObj As New DatabaseServices.ObjectIdCollection
                    sourceObj.Add(sourceTextStyleTblRec.ObjectId)
                    CurrentDatabase.WblockCloneObjects(sourceObj, CurrentTextStyleTbl.ObjectId, map, DuplicateRecordCloning.Replace, False)
                    currentTransaction.Commit()
                    Return map(sourceTextStyleTblRec.ObjectId).Value
                End Using
            End Using
        End Function
Title: Re: .NET MISCELLANEOUS/GENERAL Routines
Post by: fixo on October 16, 2010, 04:35:09 pm
= Create MlineStyle =
Code: [Select]
        public static void AddCustomMLStyle()
        {
            Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;

            Database db = doc.Database;

            Editor ed = doc.Editor;

            try
            {
                using (Transaction tr = db.TransactionManager.StartTransaction())
                {
                    //
                    DBDictionary dm = (DBDictionary)tr.GetObject(db.MLStyleDictionaryId, OpenMode.ForRead, false);

                    bool exists = false;

                    foreach (DBDictionaryEntry de in dm)
                    {
                        if (de.Key.Equals("myStyle", StringComparison.InvariantCulture))//<-- change on appropriate name here
                            exists = true;
                        break;
                    }

                    ObjectId msid = ObjectId.Null;
                    if (!exists)
                    {
                        LinetypeTable ltt = (LinetypeTable)tr.GetObject(db.LinetypeTableId, OpenMode.ForRead);
                        if (!ltt.Has("HIDDEN"))
                        {
                            Autodesk.AutoCAD.ApplicationServices.Application.ShowAlertDialog("Add code to load linetype \"HIDDEN\"");
                            return;
                        }

                        ObjectId lnid = ltt["HIDDEN"];

                        MlineStyle ms = new MlineStyle();

                        ms.Name = "myStyle";//<-- change on appropriate name here

                        ms.Description = "MLStyle for Beams etc.";//<-- change the description here (optional)

                        ms.EndSquareCap = true;

                        ms.StartSquareCap = true;

                        ms.StartInnerArcs = false;

                        ms.StartRoundCap = false;

                        ms.EndInnerArcs = false;

                        ms.EndRoundCap = false;

                        ms.ShowMiters = false;

                        ms.StartAngle = Math.PI / 2;

                        ms.EndAngle = Math.PI / 2;

                        MlineStyleElement me =
                            new MlineStyleElement(
                                0.0, Autodesk.AutoCAD.Colors.Color.FromColorIndex(Autodesk.AutoCAD.Colors.ColorMethod.ByAci, 160), ltt["Continuous"]);
                        //add elements as many as you need here
                        ms.Elements.Add(me, true);

                        me = new MlineStyleElement(
                            0.1, Autodesk.AutoCAD.Colors.Color.FromColorIndex(Autodesk.AutoCAD.Colors.ColorMethod.ByAci, 7), lnid);

                        ms.Elements.Add(me, true);

                        me = new MlineStyleElement(
                            1.0, Autodesk.AutoCAD.Colors.Color.FromColorIndex(Autodesk.AutoCAD.Colors.ColorMethod.ByAci, 160), ltt["Continuous"]);

                        ms.Elements.Add(me, true);

                        dm.UpgradeOpen();

                        msid = dm.SetAt("myStyle", ms);

                        tr.AddNewlyCreatedDBObject(ms, true);

                        dm.DowngradeOpen();
                     
                        tr.Commit();
                    }

                }
            }
            catch (Autodesk.AutoCAD.Runtime.Exception ex)
            {
                ed.WriteMessage("{0}\n{1}", ex.Message, ex.StackTrace);

            }
            finally
            {

            }
        }

~'J'~
Title: Re: .NET MISCELLANEOUS/GENERAL Routines
Post by: gile on December 07, 2010, 03:11:40 pm
Hi,

ZoomObjects (F#)

Code: [Select]
module ZoomObjects

open Autodesk.AutoCAD.ApplicationServices
open Autodesk.AutoCAD.DatabaseServices
open Autodesk.AutoCAD.EditorInput
open Autodesk.AutoCAD.Geometry
open Autodesk.AutoCAD.Runtime

let zoomObjects (ids : ObjectId[]) =
    let doc = Application.DocumentManager.MdiActiveDocument
    let db = doc.Database
    let ed = doc.Editor
    use tr = db.TransactionManager.StartTransaction()
    use view = ed.GetCurrentView()
   
    let getEnt id = tr.GetObject(id, OpenMode.ForRead) :?> Entity
   
    let addExts (ext : Extents3d) id =
        ext.AddExtents((getEnt id).GeometricExtents)
        ext
       
    let ext = ids |> Array.fold addExts (getEnt ids.[0]).GeometricExtents
    let WCS2DCS =  Matrix3d
                    .PlaneToWorld(view.ViewDirection)
                    .PreMultiplyBy(Matrix3d.Displacement(view.Target - Point3d.Origin))
                    .PreMultiplyBy(Matrix3d.Rotation(-view.ViewTwist, view.ViewDirection, view.Target))
                    .Inverse()
    ext.TransformBy(WCS2DCS)
    view.Width <- ext.MaxPoint.X - ext.MinPoint.X
    view.Height <- ext.MaxPoint.Y - ext.MinPoint.Y
    view.CenterPoint <- new Point2d((ext.MaxPoint.X + ext.MinPoint.X) / 2.0, (ext.MaxPoint.Y + ext.MinPoint.Y) / 2.0)
    ed.SetCurrentView(view)
    tr.Commit();

[<CommandMethod("ZO")>]
let zo() =
    let ed = Application.DocumentManager.MdiActiveDocument.Editor
    let psr = ed.GetSelection()
    if psr.Status = PromptStatus.OK then
        psr.Value.GetObjectIds() |> zoomObjects
Title: Re: .NET MISCELLANEOUS/GENERAL Routines
Post by: huiz on July 12, 2011, 08:34:33 am
This function checks if a command is available but does not seperate lisp commands or arx commands. Just check if the command exists.

Code: [Select]
  Shared Function IsCommandAvailable(ByVal sCmdName As String) As Boolean
    If Not Autodesk.AutoCAD.Internal.Utils.IsCommandNameInUse(sCmdName) = Autodesk.AutoCAD.Internal.CommandTypeFlags.NoneCmd Then
      Return True
    Else
      Return False
    End If
  End Function
Title: Re: .NET MISCELLANEOUS/GENERAL Routines
Post by: Jeff H on September 21, 2011, 04:25:46 pm
Coded this up quickly and was useful for having to reverse some splines because the lintype was a custom linetype with text and the text was upside down
 
Code: [Select]
        [CommandMethod("HpadRevereseSpline")]
        public void HpadRevereseSpline()
        {
       
            using (Transaction trx = db.TransactionManager.StartTransaction())
            {
                PromptEntityOptions peo = new PromptEntityOptions("\nSelect Spline: ");
                peo.SetRejectMessage("\n That was not a Spline");
                peo.AddAllowedClass(typeof(Spline), true);
                PromptEntityResult per = ed.GetEntity(peo);

                if (per.Status != PromptStatus.OK)
                {
                    return;
                }

                Spline spline = (Spline)trx.GetObject(per.ObjectId, OpenMode.ForRead);

                NurbsData nurbData = spline.NurbsData;
                Point3dCollection points = nurbData.GetControlPoints();

                int totalPoints = spline.NumControlPoints;
                int newPointIndex = totalPoints - 1;

                spline.UpgradeOpen();

                for (int i = 0; i < totalPoints; i++)
                {
                    spline.SetControlPointAt(i, points[(totalPoints - 1) - i]);
                }

                trx.Commit();

            }

        }
 
Title: Re: .NET MISCELLANEOUS/GENERAL Routines
Post by: gile on January 08, 2012, 07:05:25 am
NumericBox and IntegerBox. (EDIT: added an AngleBox)

These two three little classes can be added to a project to add new controls.
They inhertit from TextBox and have some specfic properties and overload methods to insure valid values.
An ErrorProvider is used in case of non valid entry.
Specific properties are available in the Visual Studio Properties window for the control instance.

IntegerBox
Specific properties:
- ErrorMsg: the message displayed by the ErrorProvider for incorrect value (default: "Incorrect number").
- Maximum: the maximum allowed value (default: 2147483647)
- Minimum: the minimum allowed value (default: -2147483648)
- Value: the value as integer (default 0). Setting this value overwrite the Text property.

Code: [Select]
using System;
using System.ComponentModel;
using System.Windows.Forms;

namespace ControlLibrary
{
    /// <summary>
    /// Defines a control that can be used to display or edit an integer.
    /// </summary>
    public class IntegerBox : TextBox
    {
        private ErrorProvider _errorProvider;
        private int _value;

        /// <summary>
        /// Set default values.
        /// </summary>
        public IntegerBox()
        {
            _errorProvider = new ErrorProvider();
            ErrorMsg = "Incorrect number";
            Minimum = -2147483648;
            Maximum = 2147483647;
            _value = 0;
        }

        /// <summary>
        /// Get or set the error provider message.
        /// </summary>
        public string ErrorMsg { get; set; }

        /// <summary>
        /// Get or set the minimum allowed value.
        /// </summary>
        public int Minimum { get; set; }

        /// <summary>
        /// Get or set the maximum allowed value.
        /// </summary>
        public int Maximum { get; set; }

        /// <summary>
        /// Get or set the value as integer.
        /// </summary>
        public int Value
        {
            get { return _value; }
            set
            {
                _value = value;
                this.Text = _value.ToString();
                this.OnValidating(new CancelEventArgs());
            }
        }

        /// <summary>
        /// Evaluates if the value is a valid integer according to MinValue and MaxValue.
        /// If not, cancels the validation and displayd an error provider.
        /// </summary>
        /// <param name="e">The event data.</param>
        protected override void OnValidating(System.ComponentModel.CancelEventArgs e)
        {
            base.OnValidating(e);
            int i;
            if (!int.TryParse(this.Text, out i) || i < Minimum || i > Maximum)
            {
                e.Cancel = true;
                this.Select(0, this.Text.Length);
                _errorProvider.SetError(this, ErrorMsg);
            }
        }

        /// <summary>
        /// Updates Value.
        /// </summary>
        /// <param name="e">The event data.</param>
        protected override void OnValidated(EventArgs e)
        {
            base.OnValidated(e);
            _value = Convert.ToInt32(this.Text);
        }

        /// <summary>
        /// Hide the error provider.
        /// </summary>
        /// <param name="e">The event data.</param>
        protected override void OnTextChanged(EventArgs e)
        {
            base.OnTextChanged(e);
            _errorProvider.SetError(this, "");
        }
    }
}

NumericBox
Specific properties:
- DecimalPlaces: the number of digits displayed in the box after validation (default 0)
- ErrorMsg: the message displayed by the ErrorProvider for incorrect value (default: "Incorrect number").
- Value: the value as double (default 0.0). Setting this value overwrite the Text property. This value may be more accurate than the displayed one.

Code: [Select]
using System;
using System.ComponentModel;
using System.Windows.Forms;

namespace ControlLibrary
{
    /// <summary>
    /// Defines a control that can be used to display or edit a real number (double).
    /// </summary>
    public class NumericBox : TextBox
    {
        private double _value;
        private ErrorProvider _errorProvider;
        private int _decimalPlaces;
        protected string _stringFormat;

        /// <summary>
        /// Set default values.
        /// </summary>
        public NumericBox()
        {
            _value = 0;
            _errorProvider = new ErrorProvider();
            ErrorMsg = "Incorrect number";
            SetFormat();
        }

        /// <summary>
        /// Get or set the number of digits diplayed in the box.
        /// </summary>
        public int DecimalPlaces
        {
            get { return _decimalPlaces; }
            set { _decimalPlaces = value; SetFormat(); }
        }

        /// <summary>
        /// Get or set the ErrorProvider message.
        /// </summary>
        public string ErrorMsg { get; set; }

        /// <summary>
        /// Get or set the number value as double (may be more accurate than the displayed one).
        /// Updates the Text according to DecimalPlaces.
        /// </summary>
        public virtual double Value
        {
            get { return _value; }
            set {  _value = value;  this.Text = _value.ToString(_stringFormat); }
        }

        /// <summary>
        /// Evaluates if the value is a valid real number.
        /// If not, cancels the validation and displayd the ErrorProvider icon.
        /// </summary>
        /// <param name="e">The event data</param>
        protected override void OnValidating(CancelEventArgs e)
        {
            double d;
            if (!double.TryParse(this.Text, out d))
            {
                e.Cancel = true;
                this.Select(0, this.Text.Length);
                _errorProvider.SetError(this, ErrorMsg);
            }
            base.OnValidating(e);
        }

        /// <summary>
        /// Updates Text and Value.
        /// </summary>
        /// <param name="e">The event data.</param>
        protected override void OnValidated(EventArgs e)
        {
            _value = Convert.ToDouble(this.Text);
            this.Text = _value.ToString(_stringFormat);
            base.OnValidated(e);
        }

        /// <summary>
        /// Hide the ErrorProvider icon.
        /// </summary>
        /// <param name="e">The event data.</param>
        protected override void OnTextChanged(EventArgs e)
        {
            _errorProvider.SetError(this, "");
            base.OnTextChanged(e);
        }

        /// <summary>
        /// Creates a format string according to DecimalPlaces value.
        /// Updates the Format property.
        /// </summary>
        private void SetFormat()
        {
            if (DecimalPlaces < 1)
                _stringFormat = "0";
            else
            {
                _stringFormat = "0.";
                for (int i = 0; i < DecimalPlaces; i++) _stringFormat += "0";
            }
        }
    }
}

AngleBox (inherits from NumericBox)
Specific Property:
- UnitFormat: the unit format for the Text displayed. The Value property is always expressed in radians.

Code: [Select]
using System;

namespace ControlLibrary
{
    /// <summary>
    /// Defines a control that can be used to display or edit an angular value (double).
    /// </summary>
    public class AngleBox : NumericBox
    {
        private double _value;

        /// <summary>
        /// Angular units enumeration.
        /// </summary>
        public enum Unit
        {
            Degree,
            Grade,
            Radian
        }

        /// <summary>
        /// Define the default angular unit.
        /// </summary>
        public AngleBox()
        {
            this.UnitFormat = Unit.Degree;
        }

        /// <summary>
        /// Get or set the angular format (unit).
        /// </summary>
        public Unit UnitFormat { get; set; }

        /// <summary>
        /// Get or set the angle value in radians.
        /// Updates the Text property according to UnitFormat and DecimalPlaces.
        /// </summary>
        public override double Value
        {
            get { return _value; }
            set { _value = value; this.Text = AngleToString(_value); }
        }

        /// <summary>
        /// Updates Text and Value properties.
        /// </summary>
        /// <param name="e">The event data.</param>
        protected override void OnValidated(EventArgs e)
        {
            _value = StringToAngle(this.Text);
            this.Text = AngleToString(_value);
            base.OnValidated(e);
        }

        /// <summary>
        /// Converts a string into an angle value in radians.
        /// </summary>
        /// <param name="txt">The angle expressed according to UnitFormat.</param>
        /// <returns>The angle value in radians.</returns>
        private double StringToAngle(string txt)
        {
            switch (UnitFormat)
            {
                case Unit.Degree:
                    return Convert.ToDouble(txt) * Math.PI / 180.0;
                case Unit.Grade:
                    return Convert.ToDouble(txt) * Math.PI / 200.0;
                default: //Radian
                    return Convert.ToDouble(txt);
            }
        }

        /// <summary>
        /// Converts an angle value in radians into a string.
        /// </summary>
        /// <param name="val">The angle value in radians..</param>
        /// <returns>The angle expressed according to UnitFormat</returns>
        private string AngleToString(double val)
        {
            switch (UnitFormat)
            {
                case Unit.Degree:
                    return (val * 180.0 / Math.PI).ToString(_stringFormat);
                case Unit.Grade:
                    return (val * 200.0 / Math.PI).ToString(_stringFormat);
                default: // Radian
                    return val.ToString(_stringFormat);
            }
        }
    }
}
Title: Re: .NET MISCELLANEOUS/GENERAL Routines
Post by: gile on February 10, 2012, 04:09:26 am
Hi,

I know there're many examples for writing an/or reading Excel files.

I purpose this one, it is certainly not better than some others (it *is not* regarding performance) but I thaught it was a fine example (to use 'as is' or get inspiration from).
Thanks to TonyT, Alexander Rivilis, Kaefer, Kerry Brown and all others for all I learned from them.

The ExcelReader and ExcelWriter classes try to mimic the StremReader and StreamWriter features.
They use late binding so that there's no need to reference Excel libraries which are version dependant.
A LateBinding static class is used to make the late binding expression more easy to read.

Using example:
Code - C#: [Select]
  1.        static void Main(string[] args)
  2.        {
  3.            using (ExcelWriter xlw = new ExcelWriter(@"C:\Temp\ExcelTest.xls"))
  4.            {
  5.                xlw.WriteLine(new object[3] { "foo", "bar", "baz" });
  6.                xlw.WriteLine(new object[3] { 1, 2, 3 });
  7.                xlw.Save();
  8.            }
  9.  
  10.            using (ExcelReader xlr = new ExcelReader(@"C:\Temp\ExcelTest.xls"))
  11.            {
  12.                while (!xlr.StreamEnded)
  13.                {
  14.                    foreach (object obj in xlr.ReadLine())
  15.                    {
  16.                        Console.Write("{0} ", obj);
  17.                    }
  18.                    Console.WriteLine();
  19.                }
  20.            }
  21.  
  22.            Console.ReadLine();
  23.        }


<EDIT: added some ExcelReader.ReadRange() and ExcelWriter.WriteRange() methods see here (http://www.theswamp.org/index.php?topic=40959.msg461823#msg461823).>
<EDIT: added some method to Write a Database or get a range content in a Database (thanks to kaefer)>
Title: Re: .NET MISCELLANEOUS/GENERAL Routines
Post by: gile on February 10, 2012, 09:26:21 am
The same as upper but using the 'dynamic' type instead of 'traditional' late binding (requires Framework 4.0).

<EDIT: added some ExcelReader.ReadRange() and ExcelWriter.WriteRange() methods see here (http://www.theswamp.org/index.php?topic=40959.msg461823#msg461823).>
<EDIT: added some method to Write a Database or get a range content in a Database (thanks to kaefer)>
Title: Re: .NET MISCELLANEOUS/GENERAL Routines
Post by: kosak on February 15, 2012, 09:57:58 am
Hi Gile,

could you please show in a code snippet how to use practically
the ExcelReader and ExcelWriter classes in 2 respective commands in AutoCAD ?
...let say export and import block attributes to and from Excel ...
just a tiny snippet if possible
Thanks in advance !
Title: Re: .NET MISCELLANEOUS/GENERAL Routines
Post by: gile on February 15, 2012, 01:21:37 pm
Here're two commands which work like the Express Tools ATTOUT and ATTIN.

EATT, for extracting attribute values to the specified Excel file, uses an ExcelWriter instance which is explicitly disposed if the user chooses not to open the Excel file.
IATT, for importing (and changing) attribute values, uses an ExcelReader instance in a using statement so that if is automatically disposed after reading the datas.

<EDIT: updated code tu use the new features of ExcelStreamLateBinding library>

Code - C#: [Select]
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Data;
  4. using System.IO;
  5. using System.Threading;
  6. using Autodesk.AutoCAD.DatabaseServices;
  7. using Autodesk.AutoCAD.EditorInput;
  8. using Autodesk.AutoCAD.Runtime;
  9. using Autodesk.AutoCAD.Windows;
  10. using ExcelStreamLateBinding;
  11. using AcAp = Autodesk.AutoCAD.ApplicationServices.Application;
  12.  
  13. namespace ExcelAttribute
  14. {
  15.    public class Commands
  16.    {
  17.        private string _expMsg, _dispMsg, _impMsg;
  18.        private bool _fr = Thread.CurrentThread.CurrentCulture.Name.StartsWith("fr");
  19.        private Database _db = HostApplicationServices.WorkingDatabase;
  20.        private Editor _ed = AcAp.DocumentManager.MdiActiveDocument.Editor;
  21.  
  22.        public Commands()
  23.        {
  24.            _expMsg = _fr ? "Extraction d'attributs" : "Attributes Extract";
  25.            _dispMsg = _fr ? "Ouvrir le fichier Excel ?" : "Open Excel file ?";
  26.            _impMsg = _fr ? "Importation d'attributs" : "Attributes Import";
  27.        }
  28.  
  29.        [CommandMethod("EATT", CommandFlags.UsePickSet)]
  30.        public void ExportAttributes()
  31.        {
  32.            TypedValue[] filter = new TypedValue[2] { new TypedValue(0, "INSERT"), new TypedValue(66, 1) };
  33.            PromptSelectionResult psr = _ed.GetSelection(new SelectionFilter(filter));
  34.            if (psr.Status != PromptStatus.OK) return;
  35.  
  36.            string path = string.Format("{0}{1}.xls",
  37.                AcAp.GetSystemVariable("DWGPREFIX"),
  38.                Path.GetFileNameWithoutExtension((string)AcAp.GetSystemVariable("DWGNAME")));
  39.            SaveFileDialog dlg = new SaveFileDialog(_expMsg, path, "xls;xlsx", "", 0);
  40.            if (dlg.ShowDialog() != System.Windows.Forms.DialogResult.OK) return;
  41.            string filename = dlg.Filename;
  42.  
  43.            System.Data.DataTable table = new System.Data.DataTable();
  44.            table.Columns.Add("HANDLE", typeof(String));
  45.            table.Columns.Add("NAME", typeof(String));
  46.            using (Transaction tr = _db.TransactionManager.StartTransaction())
  47.            {
  48.                foreach (SelectedObject so in psr.Value)
  49.                {
  50.                    BlockReference br = tr.GetObject(so.ObjectId, OpenMode.ForRead) as BlockReference;
  51.                    BlockTableRecord btr = br.IsDynamicBlock ?
  52.                        (BlockTableRecord)tr.GetObject(br.DynamicBlockTableRecord, OpenMode.ForRead) :
  53.                        (BlockTableRecord)tr.GetObject(br.BlockTableRecord, OpenMode.ForRead);
  54.                    table.Rows.Add(new string[2] { br.Handle.ToString(), btr.Name });
  55.                    foreach (KeyValuePair<string, string> pair in GetAttributes(br, tr))
  56.                    {
  57.                        if (!table.Columns.Contains(pair.Key))
  58.                            table.Columns.Add(pair.Key, typeof(String));
  59.                        table.Rows[table.Rows.Count - 1][pair.Key] = pair.Value;
  60.                    }
  61.                }
  62.            }
  63.  
  64.            using (ExcelWriter xlw = new ExcelWriter(filename))
  65.            {
  66.                if (File.Exists(filename))
  67.                    xlw.Clear();
  68.                xlw.WriteRange(table);
  69.                xlw.Worksheet.Get("Columns").Invoke("AutoFit");
  70.                object range = xlw.Worksheet.Get("Range",
  71.                    xlw.Worksheet.Get("Cells", 1, 1),
  72.                    xlw.Worksheet.Get("Cells", 1, table.Columns.Count));
  73.                range.Get("Font").Set("Bold", true);
  74.                xlw.Save();
  75.                if (System.Windows.Forms.MessageBox.Show(
  76.                    _dispMsg, _expMsg, System.Windows.Forms.MessageBoxButtons.YesNo) ==
  77.                    System.Windows.Forms.DialogResult.Yes)
  78.                {
  79.                    xlw.ExcelApp.Set("DisplayAlerts", true);
  80.                    xlw.ExcelApp.Set("Visible", true);
  81.                    xlw.ExcelApp.Set("UserControl", true);
  82.                }
  83.            }
  84.        }
  85.  
  86.        [CommandMethod("IATT")]
  87.        public void ImportAttributes()
  88.        {
  89.            string path = string.Format("{0}{1}.xls",
  90.                AcAp.GetSystemVariable("DWGPREFIX"),
  91.                Path.GetFileNameWithoutExtension((string)AcAp.GetSystemVariable("DWGNAME")));
  92.            OpenFileDialog dlg = new OpenFileDialog(_impMsg, path, "xls;xlsx", "", 0);
  93.            if (dlg.ShowDialog() != System.Windows.Forms.DialogResult.OK) return;
  94.            string filename = dlg.Filename;
  95.  
  96.            System.Data.DataTable table;
  97.            using (ExcelReader xlr = new ExcelReader(filename))
  98.            {
  99.                table = xlr.RangeToDataTable(1, 1);
  100.            }
  101.  
  102.            if (table == null)
  103.                return;
  104.            using (Transaction tr = _db.TransactionManager.StartTransaction())
  105.            {
  106.                foreach (DataRow row in table.Rows)
  107.                {
  108.                    try
  109.                    {
  110.                        ObjectId brId = _db.GetObjectId(false, new Handle(Convert.ToInt64(row[0].ToString(), 16)), 0);
  111.                        BlockReference br = tr.GetObject(brId, OpenMode.ForRead, true) as BlockReference;
  112.                        if (br != null)
  113.                        {
  114.                            foreach (ObjectId id in br.AttributeCollection)
  115.                            {
  116.                                AttributeReference att = (AttributeReference)tr.GetObject(id, OpenMode.ForWrite);
  117.                                if (table.Columns.Contains(att.Tag))
  118.                                {
  119.                                    att.TextString = row[att.Tag].ToString();
  120.                                }
  121.                            }
  122.                        }
  123.                    }
  124.                    catch { }
  125.                }
  126.                tr.Commit();
  127.            }
  128.        }
  129.  
  130.        private Dictionary<string, string> GetAttributes(BlockReference br, Transaction tr)
  131.        {
  132.            Dictionary<string, string> result = new Dictionary<string, string>();
  133.            foreach (ObjectId id in br.AttributeCollection)
  134.            {
  135.                AttributeReference att = (AttributeReference)tr.GetObject(id, OpenMode.ForRead);
  136.                result.Add(att.Tag.ToUpper(), att.TextString);
  137.            }
  138.            return result;
  139.        }
  140.    }
  141. }
Title: Re: .NET MISCELLANEOUS/GENERAL Routines
Post by: kosak on February 16, 2012, 06:18:43 am
http://www.theswamp.org/Smileys/aaron/grin.gif

Hi Gile,

many thanks for the example !!!
I compiled the whole project for ACAD 2011 german and everything works fine.
I will try to do the same using classes for Access 2007 and 2010.
The routines work very very fast !

best Regards
Konstantin
Title: Re: .NET MISCELLANEOUS/GENERAL Routines
Post by: kaefer on February 16, 2012, 07:02:17 am
The routines work very very fast !

Without having tested gile's youngest baby, I'd wager a guess that you could still speed up the interop data exchange part by utilizing a 2D-Array of objects for that too. This approach would reduce the number of calls to determine the Excel Range from the number of records to one, and also the number of calls to the Value2 property. An old example for this technique can be found here (http://www.theswamp.org/index.php?topic=36105.msg412423#msg412423).
Title: Re: .NET MISCELLANEOUS/GENERAL Routines
Post by: gile on February 16, 2012, 03:42:41 pm
Nice idea kaefer (as usual).
If I have some time, I'd add some WriteRange() method to the ExcelWriter class.
Title: Re: .NET MISCELLANEOUS/GENERAL Routines
Post by: airportman on December 18, 2012, 01:43:15 pm
Has anyone recompiled this to work with Autocad 2012.
I am currently having trouble with it working on my Autocad 2010.
It throws up a dialog stating:

FATAL ERROR: Unsupported version of Windows Presentation Foundation


could someone direct me to a fix for this issue?
Title: Re: .NET MISCELLANEOUS/GENERAL Routines
Post by: BlackBox on July 10, 2013, 06:57:51 pm
Resulting from this thread (http://www.theswamp.org/index.php?topic=44853.0), here are some Extension Methods for String (string):

Code - C#: [Select]
  1. using Microsoft.VisualBasic;
  2. using System.Globalization;
  3. using System.Text.RegularExpressions;
  4. using System.Threading;
  5.  
  6. namespace System
  7. {
  8.    public static class StringExtensions
  9.    {
  10.        public enum StringCase { Lower = 1, Sentence, Title, Toggle, Upper };
  11.  
  12.        public static string ToCase(this string str, int strCase)
  13.        {
  14.            string res;
  15.  
  16.            switch (strCase)
  17.            {
  18.                case (int)StringCase.Lower:
  19.                    res = str.ToLower();
  20.                    break;
  21.  
  22.                case (int)StringCase.Sentence:
  23.                    res = str.ToSentenceCase();
  24.                    break;
  25.  
  26.                case (int)StringCase.Title:
  27.                    res = str.ToTitleCase();
  28.                    break;
  29.  
  30.                case (int)StringCase.Toggle:
  31.                    res = str.ToToggleCase();
  32.                    break;
  33.  
  34.                case (int)StringCase.Upper:
  35.                    res = str.ToUpper();
  36.                    break;
  37.  
  38.                default:
  39.                    res = str;
  40.                    break;
  41.            }
  42.  
  43.            return res;
  44.        }
  45.        public static string ToSentenceCase(this String str)
  46.        {
  47.            string SentenceBreakers = Regex.Escape(".!?" + Constants.vbCrLf);
  48.            string Pattern =
  49.                "((?<=^[^" + SentenceBreakers + "\\w]{0,})[a-z]|(?<![" +
  50.                SentenceBreakers + "])(?<=[" + SentenceBreakers + "][^" +
  51.                SentenceBreakers + "\\w]{0,})[a-z])";
  52.  
  53.            return Regex.Replace(str.ToLower(), Pattern,
  54.                m => m.Value[0].ToString().ToUpper() + m.Value.Substring(1));
  55.        }
  56.        public static string ToTitleCase(this String str)
  57.        {
  58.            CultureInfo cultureInfo = Thread.CurrentThread.CurrentCulture;
  59.  
  60.            return cultureInfo.TextInfo.ToTitleCase(str.ToLower());
  61.        }
  62.        public static string ToToggleCase(this String str)
  63.        {
  64.            string newStr = "";
  65.            char[] arr = str.ToCharArray();
  66.  
  67.            foreach (char c in arr)
  68.            {
  69.                string s = c.ToString();
  70.  
  71.                if (s == s.ToLower())
  72.                    s = s.ToUpper();
  73.  
  74.                else
  75.                    s = s.ToLower();
  76.  
  77.                newStr = newStr + s;
  78.            }
  79.  
  80.            return newStr;
  81.        }
  82.    }
  83. }
  84.  
Title: Re: .NET MISCELLANEOUS/GENERAL Routines
Post by: LE3 on July 11, 2013, 03:15:19 pm
I need a way to open some drawings files and find out it is a template for a dynamic block, that way can be sorted out and send to another folder, before I do any editions on the drawings.

I am testing for these two RegApps names if they are present (per my tests on files I use here, only those two apply, if you know of any other one or have another approach, would be good to hear of that):
"AcDbDynamicBlockTrueName"
"AcDbBlockRepETag"

Code - C#: [Select]
  1.  
  2.        private static bool IsDynamicBlockFile(string fileName, List<string> filenames, Transaction transaction, Database database)
  3.        {
  4.            using (var regAppTable = (RegAppTable) transaction.GetObject(database.RegAppTableId, OpenMode.ForRead))
  5.            {
  6. #if GET_APP_NAMES
  7.                var names =
  8.            regAppTable.Cast<ObjectId>()
  9.                       .Where(id => id.IsValid)
  10.                       .Select(id => ((RegAppTableRecord)transaction.GetObject(id, OpenMode.ForRead)).Name);
  11. #endif
  12.                if (regAppTable.Cast<ObjectId>().Any(id =>
  13.                    {
  14.                        var regAppTableRecord = (RegAppTableRecord) transaction.GetObject(id, OpenMode.ForRead);
  15.                        return regAppTableRecord.Name == "AcDbDynamicBlockTrueName" || regAppTableRecord.Name == "AcDbBlockRepETag";
  16.                    }))
  17.                {
  18.                    filenames.Add(Path.GetFileName(fileName));
  19.                    return true;
  20.                }
  21.            }
  22.            return false;
  23.        }

Title: Re: .NET MISCELLANEOUS/GENERAL Routines
Post by: LE3 on July 18, 2013, 10:16:56 am
This is a tip and comment I got when started working for this company, from one of the senior programmers (Scott), that want to share, HTH.

However, I think you are being more complicated than you need to when determining when to draw the option table.
You can take all this code:

Code - C#: [Select]
  1. var anyWithJobOption = new List<bool>();
  2. foreach (var job in jobs.ItemsOnJob)
  3. {
  4.    anyWithJobOption.Add(job.HasJobOption);
  5. }
  6. var withJobOption = anyWithJobOption.Any(are => are);

And use Boolean logic instead of LINQ & Lists:
Code - C#: [Select]
  1. foreach (var job in jobs.ItemsOnJob)
  2. {
  3.    withJobOption |= job.HasJobOption;
  4. }
  5. if (withJobOption)
  6. {
  7.    // code proccess goes here...
  8. }
Title: Re: .NET MISCELLANEOUS/GENERAL Routines
Post by: fixo on May 19, 2014, 03:15:46 pm
Sample code to slicing solid multiple
Code - C#: [Select]
  1.       [CommandMethod("soc", CommandFlags.UsePickSet | CommandFlags.Redraw)]
  2.        public static void testMultySliceSolid()
  3.        {
  4.  
  5.            Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
  6.  
  7.            Database db = doc.Database;
  8.  
  9.            Editor ed = doc.Editor;
  10.            string blkname = string.Empty;
  11.  
  12.            using (Transaction trans = db.TransactionManager.StartTransaction())
  13.            {
  14.  
  15.                BlockTableRecord btr = (BlockTableRecord)trans.GetObject(db.CurrentSpaceId, OpenMode.ForWrite) as BlockTableRecord;
  16.                Solid3d sol = trans.GetObject(ed.GetEntity("\nSelect  3dSolid").ObjectId, OpenMode.ForRead) as Solid3d;
  17.  
  18.                if (sol == null)
  19.                {
  20.                    Autodesk.AutoCAD.ApplicationServices.Application.ShowAlertDialog("Nothing or wrong object selected");
  21.                    return;
  22.                }
  23.  
  24.                PromptPointOptions ppo = new PromptPointOptions("\nStarting point of slicing direction: ");
  25.                PromptPointResult ppr = ed.GetPoint(ppo);
  26.                if (ppr.Status != PromptStatus.OK) return;
  27.                PromptPointOptions pco = new PromptPointOptions("\nEnding point: ");
  28.                pco.BasePoint = ppr.Value;
  29.                pco.UseBasePoint = true;
  30.                pco.UseDashedLine = true;
  31.                PromptPointResult pcr = ed.GetPoint(pco);
  32.                if (pcr.Status != PromptStatus.OK) return;
  33.                Point3d p1 = ppr.Value;
  34.                Point3d p2 = pcr.Value;
  35.                if (p1.DistanceTo(p2)==0)
  36.                {
  37.                    ed.WriteMessage("\nInvalid coordinate specification");
  38.                    return;
  39.                }
  40.                PromptDoubleOptions pdo =
  41.                    new PromptDoubleOptions("\nEnter a slicing interval: ");
  42.                pdo.AllowNone = true;
  43.                pdo.UseDefaultValue = true;
  44.                pdo.DefaultValue = 10;
  45.  
  46.                PromptDoubleResult res;
  47.                res = ed.GetDouble(pdo);
  48.                if (res.Status != PromptStatus.OK)
  49.                    return;
  50.  
  51.                double size = res.Value;
  52.  
  53.                ed.WriteMessage("\nInterval Entered\t{0:f2}",
  54.                    size);
  55.                /*Do your stuff here*/
  56.                PromptIntegerOptions pio = new PromptIntegerOptions("");
  57.                pio.Message = "\nEnter the number of slices: ";
  58.  
  59.                // Restrict input to positive and non-negative values
  60.                pio.AllowZero = false;
  61.                pio.AllowNegative = false;
  62.                // Add default value
  63.                pio.DefaultValue = 6;
  64.                pio.AllowNone = true;
  65.  
  66.                // Get the value entered by the user
  67.                PromptIntegerResult ires = ed.GetInteger(pio);
  68.                if (ires.Status != PromptStatus.OK) return;
  69.  
  70.                int num = ires.Value;
  71.  
  72.                ed.WriteMessage("\nNumber of slices entered\t{0}", num);
  73.                /*Do your stuff here*/
  74.                double d = p1.DistanceTo(p2);
  75.  
  76.                if ((Math.Abs(d - size * num)) > 0.00001)
  77.                {
  78.                    Autodesk.AutoCAD.ApplicationServices.Application.ShowAlertDialog(string.Format(
  79.                        "Number of slices exceed a maximum, \nrecalculate number [{0}] and interval [{1}]\nif current distace is [{2}], accuratelly, please.", num, size,d));
  80.                    return;
  81.                }
  82.                // work with solid
  83.                Vector3d vec = p1.GetVectorTo(p2).GetNormal();
  84.                sol.UpgradeOpen();
  85.                Solid3d slice= new Solid3d();
  86.  
  87.                for (int i = 1; i < num; i++)
  88.                {
  89.                    Point3d spt = p1.Add(vec.MultiplyBy(size*i));
  90.                    Plane plan = new Plane(spt, vec.Negate());
  91.                    if (i == 1)
  92.                    {
  93.                         slice = sol.Slice(plan, true);
  94.                         slice.ColorIndex = 1;
  95.                         btr.AppendEntity(slice);
  96.                         trans.AddNewlyCreatedDBObject(slice, true);
  97.                    }
  98.                    else
  99.                    {
  100.                        ObjectId id = Autodesk.AutoCAD.Internal.Utils.EntLast();
  101.                         sol = (Solid3d)trans.GetObject(id, OpenMode.ForRead);
  102.                         if (!sol.IsWriteEnabled) sol.UpgradeOpen();
  103.                         slice = sol.Slice(plan, true);
  104.                         slice.ColorIndex = 1;
  105.                         btr.AppendEntity(slice);
  106.                         trans.AddNewlyCreatedDBObject(slice, true);
  107.  
  108.                    }
  109.  
  110.                }
  111.  
  112.                trans.Commit();
  113.            }
  114.        }
  115.  
Title: Re: .NET MISCELLANEOUS/GENERAL Routines
Post by: gile on November 28, 2014, 03:38:10 pm
An overload Editor.GetWindow() extension method.
The PromptWindowOptions type provides the same features as PromptPointOptions more a SecondMessage read/write property.
The PromptWindowResult type offers the same properties as PromptResult (Stauts and StringResult) plus Value of type Extents3d (current UCS coordinates).

Code - C#: [Select]
  1. using System;
  2. using Autodesk.AutoCAD.DatabaseServices;
  3.  
  4. namespace Autodesk.AutoCAD.EditorInput
  5. {
  6.    public static class EditorExtensions
  7.    {
  8.        public static PromptWindowResult GetWindow(this Editor ed, string message, string secondMessage)
  9.        {
  10.            PromptWindowOptions options = new PromptWindowOptions(message, secondMessage);
  11.            return ed.GetWindow(options);
  12.        }
  13.  
  14.        public static PromptWindowResult GetWindow(this Editor ed, string messageAndKeywords, string globalKeywords, string secondMessage)
  15.        {
  16.            PromptWindowOptions options = new PromptWindowOptions(messageAndKeywords, globalKeywords, secondMessage);
  17.            return ed.GetWindow(options);
  18.        }
  19.  
  20.        public static PromptWindowResult GetWindow(this Editor ed, PromptWindowOptions options)
  21.        {
  22.            if (ed == null)
  23.                throw new ArgumentNullException("ed");
  24.  
  25.            if (options == null)
  26.                throw new ArgumentNullException("options");
  27.  
  28.            Extents3d value = new Extents3d();
  29.            PromptPointResult result = ed.GetPoint(options);
  30.  
  31.            if (result.Status == PromptStatus.Keyword)
  32.                return new PromptWindowResult(result.Status, result.StringResult);
  33.  
  34.            if (result.Status != PromptStatus.OK)
  35.                return new PromptWindowResult(result.Status);
  36.  
  37.            value.AddPoint(result.Value);
  38.            result = ed.GetCorner(options.SecondMessage, result.Value);
  39.  
  40.            if (result.Status != PromptStatus.OK)
  41.                return new PromptWindowResult(result.Status);
  42.  
  43.            value.AddPoint(result.Value);
  44.            return new PromptWindowResult(result.Status, value);
  45.        }
  46.    }
  47.  
  48.    public class PromptWindowOptions : PromptPointOptions
  49.    {
  50.        public string SecondMessage { get; set; }
  51.  
  52.        public PromptWindowOptions(string message, string secondMessage)
  53.            : base(message)
  54.        {
  55.            this.SecondMessage = secondMessage;
  56.        }
  57.  
  58.        public PromptWindowOptions(string messageAndKeywords, string globalKeywords, string secondMessage)
  59.            : base(messageAndKeywords, globalKeywords)
  60.        {
  61.            this.SecondMessage = secondMessage;
  62.        }
  63.    }
  64.  
  65.    public class PromptWindowResult
  66.    {
  67.        public string StringResult { get; private set; }
  68.  
  69.        public PromptStatus Status { get; private set; }
  70.  
  71.        public Extents3d Value { get; private set; }
  72.  
  73.        internal PromptWindowResult(PromptStatus status, Extents3d value)
  74.        {
  75.            this.Status = status;
  76.            this.Value = value;
  77.        }
  78.  
  79.        internal PromptWindowResult(PromptStatus status, string keyword)
  80.            : this(status)
  81.        {
  82.            this.StringResult = keyword;
  83.        }
  84.  
  85.        internal PromptWindowResult(PromptStatus status)
  86.            : this(status, new Extents3d()) { }
  87.    }
  88. }
  89.  

A test command example:
Code - C#: [Select]
  1.        [CommandMethod("Test")]
  2.        public void Test()
  3.        {
  4.            Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
  5.  
  6.            PromptWindowOptions options =
  7.                new PromptWindowOptions(
  8.                    "\nSpecify first corner [Extents/Previous]: ",
  9.                    "Extents Previous",
  10.                    "\nSpecify opposite corner");
  11.            options.AllowNone = true;
  12.  
  13.            dynamic acadApp = Application.AcadApplication;
  14.  
  15.            while (true)
  16.            {
  17.                PromptWindowResult result = ed.GetWindow(options);
  18.                switch (result.Status)
  19.                {
  20.                    case PromptStatus.Keyword:
  21.                        if (result.StringResult == "Extents")
  22.                            acadApp.Zoomextents();
  23.                        else
  24.                            acadApp.ZoomPrevious();
  25.                        break;
  26.                    case PromptStatus.OK:
  27.                        var exts = result.Value;
  28.                        exts.TransformBy(ed.CurrentUserCoordinateSystem);
  29.                        acadApp.ZoomWindow(exts.MinPoint.ToArray(), exts.MaxPoint.ToArray());
  30.                        break;
  31.                    default:
  32.                        return;
  33.                }
  34.            }
  35.        }
Title: Re: .NET MISCELLANEOUS/GENERAL Routines
Post by: gile on January 23, 2015, 02:28:57 pm
Hi,

These some helpers allow to access AutoCAD registry data from outside AutoCAD.
This may be usefull with installing / deinstalling applications.

<EDIT: added a ServicePack property to the ProductKey class>
<EDIT: changed the GetCurrentProductKey() and GetAllProductKeys() implementation to a safer one>
<EDIT: corrected some copy/paste errors>
<EDIT: updated code to handle ServicePacks Autodesk registry>

AcadReg class provides static methods to get AutoCAD registry product keys
Code - C#: [Select]
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text.RegularExpressions;
  5. using Microsoft.Win32;
  6.  
  7. namespace Gile.AutocadRegistryServices
  8. {
  9.    public static class AcadReg
  10.    {
  11.        public static ProductKey GetCurrentProductKey()
  12.        {
  13.            string key = @"Software\Autodesk\AutoCAD";
  14.            using (RegistryKey root = Registry.CurrentUser.OpenSubKey(key))
  15.            {
  16.                if (root == null)
  17.                    throw new InvalidOperationException(string.Format("'{0}' = null", key));
  18.                string curver = (string)root.GetValue("CurVer");
  19.                if (string.IsNullOrEmpty(curver))
  20.                    throw new InvalidOperationException(string.Format("'{0}' CurVer = null", key));
  21.                key += "\\" + curver;
  22.                using (RegistryKey rkey = Registry.CurrentUser.OpenSubKey(key))
  23.                {
  24.                    curver = (string)rkey.GetValue("CurVer");
  25.                    if (string.IsNullOrEmpty(curver))
  26.                        throw new InvalidOperationException(string.Format("'{0}' CurVer = null", key));
  27.                    return new ProductKey(key + "\\" + curver);
  28.                }
  29.            }
  30.        }
  31.  
  32.        public static IEnumerable<ProductKey> GetAllProductKeys()
  33.        {
  34.            string prefix = @"Software\Autodesk\AutoCAD";
  35.            using (RegistryKey root = Registry.CurrentUser.OpenSubKey(prefix))
  36.            {
  37.                return root.GetSubKeyNames()
  38.                    .Select(s => string.Format(@"{0}\{1}", prefix, s))
  39.                    .SelectMany(s => Registry.CurrentUser.OpenSubKey(s).GetSubKeyNames()
  40.                        .Where(k => Regex.IsMatch(k, "^ACAD-....:..."))
  41.                        .Select(k => new ProductKey(string.Format(@"{0}\{1}", s, k))));
  42.            }
  43.        }
  44.  
  45.        public static IEnumerable<ProductKey> GetProductKeysSince(string release)
  46.        {
  47.            return GetProductKeysSince(release, GetAllProductKeys());
  48.        }
  49.  
  50.        public static IEnumerable<ProductKey> GetProductKeysSince(string release, IEnumerable<ProductKey> source)
  51.        {
  52.            if (!(Regex.IsMatch(release, @"^R\d\d$|^R\d\d.\d$")))
  53.                throw new FormatException("Incorrect Release format: " + release);
  54.  
  55.            if (source == null)
  56.                throw new ArgumentNullException("source");
  57.  
  58.            return source.Where(pk => pk.Release.CompareTo(release) >= 0);
  59.        }
  60.    }
  61. }

ProductKey class provides methods and properties to deal with AutoCAD registry product key
Public properties
Public instance methods
Code - C#: [Select]
  1. using System.Collections.Generic;
  2. using System.IO;
  3. using System.Linq;
  4. using Microsoft.Win32;
  5.  
  6. namespace Gile.AutocadRegistryServices
  7. {
  8.    public class ProductKey
  9.    {
  10.        public string KeyName { get; private set; }
  11.  
  12.        public string Release { get; private set; }
  13.  
  14.        public string ProductId { get; private set; }
  15.  
  16.        public string LocaleId { get; private set; }
  17.  
  18.        public string ServicePack { get; private set; }
  19.  
  20.        internal ProductKey(string keyName)
  21.        {
  22.            KeyName = keyName;
  23.            string[] items = keyName.Split('\\');
  24.            Release = items[3];
  25.            string[] ids = items[4].Substring(5).Split(':');
  26.            ProductId = ids[0];
  27.            LocaleId = ids[1];
  28.            string subKeyName = Release.CompareTo("R19.0") < 0 ?
  29.                subKeyName = keyName + "\\Service Packs" :
  30.                Path.Combine(Path.GetDirectoryName(keyName), "ACAD-" + ProductId + "\\Service Packs");
  31.            using (RegistryKey rkey = Registry.LocalMachine.OpenSubKey(subKeyName))
  32.            {
  33.                if (rkey == null)
  34.                {
  35.                    ServicePack = "";
  36.                }
  37.                else
  38.                {
  39.                    subKeyName += "\\" + rkey.GetSubKeyNames()[0];
  40.                    using (RegistryKey subKey = Registry.LocalMachine.OpenSubKey(subKeyName))
  41.                    {
  42.                        string productName = (string)subKey.GetValue("ProductName");
  43.                        string patchTitle = (string)subKey.GetValue("PatchTitle");
  44.                        ServicePack = patchTitle.Length > productName.Length ?
  45.                            patchTitle.Substring(productName.Length + 1) :
  46.                            productName.Substring(patchTitle.Length + 1);
  47.                    }
  48.                }
  49.            }
  50.        }
  51.  
  52.        public IEnumerable<ProfileKey> GetProfileKeys()
  53.        {
  54.            string profiles = string.Format(@"{0}\Profiles", KeyName);
  55.            using (RegistryKey rkey = Registry.CurrentUser.OpenSubKey(profiles))
  56.            {
  57.                return rkey.GetSubKeyNames()
  58.                    .Select(skn => new ProfileKey(string.Format(@"{0}\{1}", profiles, skn)));
  59.            }
  60.        }
  61.  
  62.        public void RegisterApplication(
  63.            string appName,
  64.            string fileName,
  65.            string description,
  66.            bool allUsers = false,
  67.            string[] globalCmdNames = null,
  68.            string[] localCmdNames = null,
  69.            string[] groups = null)
  70.        {
  71.            RegistryKey hive = allUsers ?
  72.                RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64) :
  73.                Registry.CurrentUser;
  74.            string apps = string.Format(@"{0}\Applications", KeyName);
  75.            using (RegistryKey appsKey = hive.OpenSubKey(apps, true))
  76.            {
  77.                if (appsKey.GetSubKeyNames().Contains(appName))
  78.                    return;
  79.                int flags =
  80.                    globalCmdNames != null &&
  81.                    localCmdNames != null &&
  82.                    globalCmdNames.Length > 0 &&
  83.                    globalCmdNames.Length == localCmdNames.Length ?
  84.                    12 : 2;
  85.                using (RegistryKey appKey = appsKey.CreateSubKey(appName))
  86.                {
  87.                    appKey.SetValue("DESCRIPTION", description, RegistryValueKind.String);
  88.                    appKey.SetValue("LOADCTRLS", flags, RegistryValueKind.DWord);
  89.                    appKey.SetValue("LOADER", fileName, RegistryValueKind.String);
  90.                    appKey.SetValue("MANAGED", 1, RegistryValueKind.DWord);
  91.  
  92.                    if (flags == 12)
  93.                    {
  94.                        using (RegistryKey cmdKey = appKey.CreateSubKey("Commands"))
  95.                        {
  96.                            for (int i = 0; i < globalCmdNames.Length; i++)
  97.                            {
  98.                                cmdKey.SetValue(globalCmdNames[i], localCmdNames[i], RegistryValueKind.String);
  99.                            }
  100.                        }
  101.                        if (groups != null && groups.Length > 0)
  102.                        {
  103.                            using (RegistryKey grpKey = appKey.CreateSubKey("Groups"))
  104.                            {
  105.                                foreach (string grpName in groups)
  106.                                {
  107.                                    grpKey.SetValue(grpName, grpName, RegistryValueKind.String);
  108.                                }
  109.                            }
  110.                        }
  111.                    }
  112.                }
  113.            }
  114.        }
  115.  
  116.        public void UnregisterApplication(string appName, bool allUsers = false)
  117.        {
  118.            RegistryKey hive = allUsers ?
  119.                RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64) :
  120.                Registry.CurrentUser;
  121.            string apps = string.Format(@"{0}\Applications", KeyName);
  122.            using (RegistryKey appsKey = hive.OpenSubKey(apps, true))
  123.            {
  124.                if (appsKey.GetSubKeyNames().Contains(appName))
  125.                appsKey.DeleteSubKeyTree(appName);
  126.            }
  127.        }
  128.  
  129.        public void RegisterSystemVariable(
  130.            string name,
  131.            object defaultValue,
  132.            SysVar.StorageType storageType,
  133.            SysVar.PrimaryType primaryType,
  134.            SysVar.SecondaryType secondaryType = SysVar.SecondaryType.None,
  135.            int lowerBound = int.MinValue,
  136.            int upperBound = int.MaxValue,
  137.            SysVar.TypeFlags typeFlags = SysVar.TypeFlags.None,
  138.            string owner = "")
  139.        {
  140.            if (Release.CompareTo("R18.1") < 0)
  141.                return;
  142.            RegistryKey hive = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64);
  143.            string apps = string.Format(@"{0}\Variables", KeyName);
  144.            using (RegistryKey varsKey = hive.OpenSubKey(apps, true))
  145.            {
  146.                if (varsKey.GetSubKeyNames().Contains(name))
  147.                    return;
  148.                using (RegistryKey key = varsKey.CreateSubKey(name))
  149.                {
  150.                    key.SetValue("", defaultValue, RegistryValueKind.String);
  151.                    key.SetValue("PrimaryType", (int)primaryType, RegistryValueKind.DWord);
  152.                    if (secondaryType != SysVar.SecondaryType.None)
  153.                        key.SetValue("SecondaryType", (int)secondaryType, RegistryValueKind.DWord);
  154.                    if (typeFlags != SysVar.TypeFlags.None)
  155.                        key.SetValue("TypeFlags", (int)typeFlags, RegistryValueKind.DWord);
  156.                    key.SetValue("StorageType", (int)storageType, RegistryValueKind.DWord);
  157.                    if (owner != "")
  158.                        key.SetValue("Owner", owner, RegistryValueKind.String);
  159.                    if (primaryType == SysVar.PrimaryType.String)
  160.                    {
  161.                        if (lowerBound != int.MinValue)
  162.                            key.SetValue("LowerBound", (int)lowerBound, RegistryValueKind.DWord);
  163.                        if (upperBound != int.MaxValue)
  164.                            key.SetValue("UpperBound", (int)upperBound, RegistryValueKind.DWord);
  165.                    }
  166.                }
  167.            }
  168.        }
  169.  
  170.        public void UnregisterSystemVariable(string name)
  171.        {
  172.            if (Release.CompareTo("R18.1") < 0)
  173.                return;
  174.            RegistryKey hive = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64);
  175.            string apps = string.Format(@"{0}\Variables", KeyName);
  176.            using (RegistryKey varsKey = hive.OpenSubKey(apps, true))
  177.            {
  178.                varsKey.DeleteSubKey(name, false);
  179.            }
  180.        }
  181.    }
  182. }

ProfileKey class provides methods and properties to deal with AutoCAD registry profile key
Public properties
Public instance methods
Code - C#: [Select]
  1. using System;
  2. using System.Linq;
  3. using System.Text;
  4. using Microsoft.Win32;
  5.  
  6. namespace Gile.AutocadRegistryServices
  7. {
  8.    public class ProfileKey
  9.    {
  10.        public string KeyName { get; private set; }
  11.  
  12.        public string Name { get; private set; }
  13.  
  14.        internal ProfileKey(string key)
  15.        {
  16.            string[] items = key.Split('\\');
  17.            KeyName = key;
  18.            Name = items[6];
  19.        }
  20.  
  21.        public void AppendSupportPath(string path)
  22.        {
  23.            AppendPath("General", "ACAD", path);
  24.        }
  25.  
  26.        public void PrependSupportPath(string path)
  27.        {
  28.            PrependPath("General", "ACAD", path);
  29.        }
  30.  
  31.        public void AddTrustedPath(string path)
  32.        {
  33.            if (KeyName.Split('\\')[3].CompareTo("R19.1") >= 0)
  34.                AppendPath("Variables", "TRUSTEDPATHS", path);
  35.        }
  36.  
  37.        public void RemoveSupportPath(string path)
  38.        {
  39.            RemovePath("General", "ACAD", path);
  40.        }
  41.  
  42.        public void RemoveTrustedPath(string path)
  43.        {
  44.            if (KeyName.Split('\\')[3].CompareTo("R19.1") >= 0)
  45.                RemovePath("Variables", "TRUSTEDPATHS", path);
  46.        }
  47.  
  48.        private void AppendPath(string subKey, string value, string path)
  49.        {
  50.            string key = string.Format(@"{0}\{1}", KeyName, subKey);
  51.            using (RegistryKey rkey = Registry.CurrentUser.OpenSubKey(key, true))
  52.            {
  53.                string paths = (string)rkey.GetValue(value);
  54.                if (!paths.EndsWith(";"))
  55.                    paths += ";";
  56.                if (!paths.Split(';').Select(s => s.ToUpper()).Contains(path.ToUpper()))
  57.                {
  58.                    paths += path + ";";
  59.                    rkey.SetValue(value, paths);
  60.                }
  61.            }
  62.        }
  63.  
  64.        private void PrependPath(string subKey, string value, string path)
  65.        {
  66.            string key = string.Format(@"{0}\{1}", KeyName, subKey);
  67.            using (RegistryKey rkey = Registry.CurrentUser.OpenSubKey(key, true))
  68.            {
  69.                string paths = (string)rkey.GetValue(value);
  70.                if (!paths.EndsWith(";"))
  71.                    paths += ";";
  72.                if (!paths.Split(';').Select(s => s.ToUpper()).Contains(path.ToUpper()))
  73.                {
  74.                    paths = path + ";" + paths;
  75.                    rkey.SetValue(value, paths);
  76.                }
  77.            }
  78.        }
  79.  
  80.        private void RemovePath(string subKey, string value, string path)
  81.        {
  82.            string key = string.Format(@"{0}\{1}", KeyName, subKey);
  83.            using (RegistryKey rkey = Registry.CurrentUser.OpenSubKey(key, true))
  84.            {
  85.                string str = (string)rkey.GetValue(value);
  86.                if (str == null) return;
  87.                string[] paths = str.Split(';');
  88.                StringBuilder sb = new StringBuilder();
  89.                foreach (string s in paths)
  90.                {
  91.                    if (s != string.Empty &&
  92.                        !s.Equals(path, StringComparison.CurrentCultureIgnoreCase))
  93.                        sb.Append(s).Append(";");
  94.                }
  95.                rkey.SetValue(value, sb.ToString());
  96.            }
  97.        }
  98.    }
  99. }

SysVar class provides enums similar to the AutoCAD.Runtime.Variable ones to make the code more readable
Code - C#: [Select]
  1. using System;
  2.  
  3. namespace Gile.AutocadRegistryServices
  4. {
  5.    public class SysVar
  6.    {
  7.        public enum StorageType
  8.        {
  9.            PerSession = 0,
  10.            PerUser = 1,
  11.            PerProfile = 2,
  12.            PerDatabase = 3
  13.        }
  14.  
  15.        public enum PrimaryType
  16.        {
  17.            Double = 5001,
  18.            Short = 5003,
  19.            String = 5005,
  20.            Integer = 5010
  21.        }
  22.  
  23.        public enum SecondaryType
  24.        {
  25.            None = 0,
  26.            Boolean = 1,
  27.            SymbolName = 2,
  28.            Area = 3,
  29.            Distance = 4,
  30.            Angle = 5,
  31.            UnitlessReal = 6
  32.        }
  33.  
  34.        [Flags]
  35.        public enum TypeFlags
  36.        {
  37.            None = 0,
  38.            SpacesAllowed = 1,
  39.            DotMeansEmpty = 2,
  40.            NoUndo = 4,
  41.            Chatty = 8
  42.        }
  43.    }
  44. }

Using example to install a .NET DLL for all profiles of all products installed for the current user:
Code - C#: [Select]
  1.        /// <summary>
  2.        /// Install a .NET application
  3.        /// </summary>
  4.        /// <param name="fileName">The DLL full path.</param>
  5.        public void Install(string fileName)
  6.        {
  7.            string folder = System.IO.Path.GetDirectoryName(fileName);
  8.            string appName = System.IO.Path.GetFileNameWithoutExtension(fileName);
  9.  
  10.            // for all AutoCAD products
  11.            foreach (ProductKey prodKey in AcadReg.GetAllProductKeys())
  12.            {
  13.                // add the support path to each profile
  14.                foreach (ProfileKey key in prodKey.GetProfileKeys())
  15.                {
  16.                    key.AddSupportPath(folder);
  17.                }
  18.                // register the application
  19.                prodKey.RegisterApplication(appName, fileName, appName);
  20.            }
  21.  
  22.            // for AutoCAD products since 2014
  23.            var trusted =
  24.                AcadReg.GetProductKeysSince("R19.1")
  25.                .SelectMany(k => k.GetProfileKeys());
  26.            // add the trusted path to each profile
  27.            foreach (ProfileKey key in trusted)
  28.            {
  29.                key.AddTrustedPath(folder);
  30.            }
  31.        }

Using example to uninstall a .NET DLL:
Code - C#: [Select]
  1.        /// <summary>
  2.        /// Uninstall a .NET application
  3.        /// </summary>
  4.        /// <param name="fileName">The DLL full path.</param>
  5.        public void Uninstall(string fileName)
  6.        {
  7.            string folder = System.IO.Path.GetDirectoryName(fileName);
  8.            string appName = System.IO.Path.GetFileNameWithoutExtension(fileName);
  9.  
  10.            // for all AutoCAD products
  11.            foreach (ProductKey prodKey in AcadReg.GetAllProductKeys())
  12.            {
  13.                // remove the support path from each profil
  14.                foreach (ProfileKey key in prodKey.GetProfileKeys())
  15.                {
  16.                    key.RemoveSupportPath(folder);
  17.                }
  18.                // unregister the application
  19.                prodKey.UnregisterApplication(appName);
  20.            }
  21.  
  22.            // for AutoCAD products since 2014
  23.            var trusted =
  24.                AcadReg.GetProductKeysSince("R19.1")
  25.                .SelectMany(k => k.GetProfileKeys());
  26.            // remove the trusted path from each profile
  27.            foreach (ProfileKey key in trusted)
  28.            {
  29.                key.RemoveTrustedPath(folder);
  30.            }
  31.        }
Title: Re: .NET MISCELLANEOUS/GENERAL Routines
Post by: Dashmonkey on July 20, 2015, 04:41:53 pm
Gile, I'm loving your AcadReg class! It's SUPER slick and I learned a lot from looking at it. Thanks for posting :D
Title: Re: .NET MISCELLANEOUS/GENERAL Routines
Post by: Keith Brown on August 12, 2015, 02:42:18 pm
Hi Gile,

In some of your methods in the Registry Classes I had to change your OpenSubKey calls to open with ReadWrite status.  For instance in the AddPath method of the ProfileKey class I changed

Code - C#: [Select]
  1. using (var rkey= Registry.CurrentUser.OpenSubKey(key))

to

Code - C#: [Select]
  1. using (var rkey= Registry.CurrentUser.OpenSubKey(key, true))

I had to do this in several places where the value of the key was being modified.  Not sure if that was because of my permissions or something else.  I think that you are also missing the servicePack private string variable in the ProductKey class.  Other than that it worked great for me when installing a dll.
Title: Re: .NET MISCELLANEOUS/GENERAL Routines
Post by: Area51Visitor on August 12, 2015, 09:28:38 pm
Toggles extension line for aligned dimension...doesn't account for exact middle pick but found it's never been a problem:

Code - C#: [Select]
  1.        [CommandMethod("TOGE")]
  2.        public static void RemoveAddExtensions()
  3.        {
  4.            CivilDocument CivDoc = Autodesk.Civil.ApplicationServices.CivilApplication.ActiveDocument;
  5.            Document AcadDoc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
  6.            Editor MyEditor = Application.DocumentManager.MdiActiveDocument.Editor;
  7.            Database MyDatabase = HostApplicationServices.WorkingDatabase;
  8.  
  9.            using (DocumentLock acLckDoc = AcadDoc.LockDocument())
  10.            {
  11.                using (Transaction MyTrans = MyDatabase.TransactionManager.StartTransaction())
  12.                {
  13.                    try
  14.                    {
  15.                        ObjectId mydimoid = promptfordim("\nSelect Dimension: ");
  16.                        AlignedDimension mydim = (AlignedDimension)MyTrans.GetObject(mydimoid, OpenMode.ForRead);
  17.                        Point3d mypoint = GetMyPoint("\nSelect Point Near Extension: ");
  18.                        mydim.UpgradeOpen();
  19.  
  20.                        if ((mypoint.DistanceTo(mydim.XLine1Point)) < (mypoint.DistanceTo(mydim.XLine2Point)))
  21.                        {
  22.                            if (mydim.Dimse1 == true)
  23.                            {
  24.                                mydim.Dimse1 = false;
  25.                            }
  26.                            else
  27.                            {
  28.                                mydim.Dimse1 = true;
  29.                            }
  30.                        }
  31.                        else
  32.                        {
  33.                            if (mydim.Dimse2 == true)
  34.                            {
  35.                                mydim.Dimse2 = false;
  36.                            }
  37.                            else
  38.                            {
  39.                                mydim.Dimse2 = true;
  40.                            }
  41.                        }
  42.                        mydim.DowngradeOpen();
  43.                    }
  44.                    catch (System.Exception ex)
  45.                    {
  46.                        MyEditor.WriteMessage("Error: ==>\n{0}\nTrace: ==>\n{1}", ex.Message, ex.StackTrace);
  47.                    }
  48.                    MyTrans.Commit();
  49.                }
  50.            }
  51.        }[code]
Title: Re: .NET MISCELLANEOUS/GENERAL Routines
Post by: gile on August 14, 2015, 04:09:21 am
Hi Gile,

In some of your methods in the Registry Classes I had to change your OpenSubKey calls to open with ReadWrite status.  For instance in the AddPath method of the ProfileKey class I changed

Code - C#: [Select]
  1. using (var rkey= Registry.CurrentUser.OpenSubKey(key))

to

Code - C#: [Select]
  1. using (var rkey= Registry.CurrentUser.OpenSubKey(key, true))

I had to do this in several places where the value of the key was being modified.  Not sure if that was because of my permissions or something else.  I think that you are also missing the servicePack private string variable in the ProductKey class.  Other than that it worked great for me when installing a dll.
Many thanks for reporting Keith.
I corrected the posted code.
Title: Re: .NET MISCELLANEOUS/GENERAL Routines
Post by: RICVBA on August 23, 2015, 03:19:06 am
Nice idea kaefer (as usual).
If I have some time, I'd add some WriteRange() method to the ExcelWriter class.

Hi Everybody
I'm a rather discontinuos learner of C# and NET, with the main purpose of Autocad Automation and its Excel connection
These days, I peeped in this thread to try and learn "true life" coding and state-of-the-art "how to"'s,

While learning a lot (and realizing there's a very lot more to - probably too much!), I assumed it could be a useful exercise to make some add-on and see what I actually grasped of it

so I'm attacching a LateBinding solution "ExcelReader" class with minor modifications to let you deal with Excel data written in and read from ranges not beginning at cell (1,1)
In detail, I modifed the following ExcelReader methods:
- ExcelReader main constructor
- SetActiveSheet()
- Peak()
- NewLine()
- Read() (the main method)
- ReadLine() (the main method)
- ReadRange() (both methods)
- RangeToDataTable() (both methods)
all modifications are clearly marked and I also mantained (commented) the corresponding original code lines

to test it I slightly modified Gile's using example as follows:

Using Example:
Code: [Select]
class Program
    {
        static void Main(string[] args)
        {
            using (ExcelWriter xlw = new ExcelWriter(@"C:\Users\Riccardo\Documents\Cartel2.xlsx"))
            {
                xlw.Clear();
                xlw.WriteLine(new object[3] { "foo", "bar", "baz" }, 3, 2); //<------ modified by RICVBA to have a usedrange not beginning at cells(1,1)
                xlw.WriteLine(new object[3] { 1, 2, 3 }, 4, 3);             //<------ modified by RICVBA to have a usedrange not beginning at cells(1,1)
                xlw.Save();
            }

            using (ExcelReader xlr = new ExcelReader(@"C:\Users\Riccardo\Documents\Cartel2.xlsx"))
            {
                while (!xlr.StreamEnded)
                {
                    foreach (object obj in xlr.ReadLine())
                    {
                        Console.Write("{0} ", obj);
                    }
                    Console.WriteLine();
                }

                //------------------------------------------
                //added by RICVBA to test some methods after ExcelReader class modifications
                wl(xlr.ReadToEnd()); // should work as it was
                wl(xlr.ReadRange(2, 1)); // modified
                //------------------------------------------

            }

            Console.ReadLine();
        }

        //------------------------------------------
        //added by RICVBA
        static void wl(object[,] range)
        {
            for (int i = 0; i < range.GetLength(0); i++)
            {
                for (int j = 0; j < range.GetLength(1); j++)
                {
                    Console.Write("{0} ", range[i, j]);
                }
                Console.WriteLine();
            }
        }
        //------------------------------------------


as per my tests, it worked.
if confirmed, same modifications for Dynamic solution's same class should be straightforward
If anybody interested in giving feedbacks, please do.

thank you   
Title: Re: .NET MISCELLANEOUS/GENERAL Routines
Post by: gile on October 01, 2015, 02:36:38 pm
Hi,

I updated the code of AutocadRegistryServices (http://www.theswamp.org/index.php?topic=31867.msg538136#msg538136) to handle the reversed values of PatchTitle and ProductName in the registry with AutoCAD 2016 SP1.

(http://gile.pagesperso-orange.fr/AutoCAD_SP.png)
Title: Re: .NET MISCELLANEOUS/GENERAL Routines
Post by: gile on March 10, 2017, 05:09:40 pm
Hi,

Some extension methods to perform different kinds of zoom.

Code - C#: [Select]
  1. using Autodesk.AutoCAD.ApplicationServices;
  2. using Autodesk.AutoCAD.DatabaseServices;
  3. using Autodesk.AutoCAD.Geometry;
  4. using Autodesk.AutoCAD.Runtime;
  5. using System;
  6. using System.Collections.Generic;
  7. using System.Linq;
  8.  
  9. namespace Autodesk.AutoCAD.EditorInput
  10. {
  11.    public static class ExtensionMethods
  12.    {
  13.        public static Matrix3d EyeToWorld(this ViewTableRecord view)
  14.        {
  15.            if (view == null)
  16.                throw new ArgumentNullException("view");
  17.  
  18.            return
  19.                Matrix3d.Rotation(-view.ViewTwist, view.ViewDirection, view.Target) *
  20.                Matrix3d.Displacement(view.Target - Point3d.Origin) *
  21.                Matrix3d.PlaneToWorld(view.ViewDirection);
  22.        }
  23.  
  24.        public static Matrix3d WorldToEye(this ViewTableRecord view)
  25.        {
  26.            return view.EyeToWorld().Inverse();
  27.        }
  28.  
  29.        public static void Zoom(this Editor ed, Extents3d ext)
  30.        {
  31.            if (ed == null)
  32.                throw new ArgumentNullException("ed");
  33.  
  34.            using (ViewTableRecord view = ed.GetCurrentView())
  35.            {
  36.                ext.TransformBy(view.WorldToEye());
  37.                view.Width = ext.MaxPoint.X - ext.MinPoint.X;
  38.                view.Height = ext.MaxPoint.Y - ext.MinPoint.Y;
  39.                view.CenterPoint = new Point2d(
  40.                    (ext.MaxPoint.X + ext.MinPoint.X) / 2.0,
  41.                    (ext.MaxPoint.Y + ext.MinPoint.Y) / 2.0);
  42.                ed.SetCurrentView(view);
  43.            }
  44.        }
  45.  
  46.        public static void ZoomExtents(this Editor ed)
  47.        {
  48.            if (ed == null)
  49.                throw new ArgumentNullException("ed");
  50.  
  51.            Database db = ed.Document.Database;
  52.            Extents3d ext = (short)Application.GetSystemVariable("cvport") == 1 ?
  53.                new Extents3d(db.Pextmin, db.Pextmax) :
  54.                new Extents3d(db.Extmin, db.Extmax);
  55.            ed.Zoom(ext);
  56.        }
  57.  
  58.        public static void ZoomWindow(this Editor ed, Point3d p1, Point3d p2)
  59.        {
  60.            using (Line line = new Line(p1, p2))
  61.            {
  62.                ed.Zoom(line.GeometricExtents);
  63.            }
  64.        }
  65.  
  66.        public static void ZoomScale(this Editor ed, double scale)
  67.        {
  68.            if (ed == null)
  69.                throw new ArgumentNullException("ed");
  70.  
  71.            using (ViewTableRecord view = ed.GetCurrentView())
  72.            {
  73.                view.Width /= scale;
  74.                view.Height /= scale;
  75.                ed.SetCurrentView(view);
  76.            }
  77.        }
  78.  
  79.        public static void ZoomObjects(this Editor ed, IEnumerable<ObjectId> ids)
  80.        {
  81.            if (ed == null)
  82.                throw new ArgumentNullException("ed");
  83.  
  84.            using (Transaction tr = ed.Document.TransactionManager.StartTransaction())
  85.            {
  86.                Extents3d ext = ids
  87.                    .Where(id => id.ObjectClass.IsDerivedFrom(RXObject.GetClass(typeof(Entity))))
  88.                    .Select(id => ((Entity)tr.GetObject(id, OpenMode.ForRead)).GeometricExtents)
  89.                    .Aggregate((e1, e2) => { e1.AddExtents(e2); return e1; });
  90.                ed.Zoom(ext);
  91.                tr.Commit();
  92.            }
  93.        }
  94.  
  95.        public static void ZoomCenter(this Editor ed, Point3d center, double scale = 1.0)
  96.        {
  97.            if (ed == null)
  98.                throw new ArgumentNullException("ed");
  99.  
  100.            using (ViewTableRecord view = ed.GetCurrentView())
  101.            {
  102.                center = center.TransformBy(view.WorldToEye());
  103.                view.Height /= scale;
  104.                view.Width /= scale;
  105.                view.CenterPoint = new Point2d(center.X, center.Y);
  106.                ed.SetCurrentView(view);
  107.            }
  108.        }
  109.    }
  110. }
  111.  
Title: Re: .NET MISCELLANEOUS/GENERAL Routines
Post by: Keith Brown on March 16, 2017, 02:00:12 pm
Hi,
Some extension methods to perform different kinds of zoom.


Hi Gile,


Nice code but you might want to wrap your max minus min functions in an absolute value call before passing to the width and height of the view.  Autocad seems to handle it fine with out the absolute function call but Bricscad will throw an exception when both points are in negative territory.  Autocad must be automatically taking the absolute value of the width and height where Teigha (bricscad) is not.