Pular para o conteúdo principal

Lendo arquivos de Excel do AutoCAD

Acho que uma das principais coisas que todos nós fazemos é tratar uma informação que está dentro do Excel. Assim como o AutoCAD o Excel se tornou uma ferramenta de engenharia mais poderosa que o próprio Matlab por um único motivo: é o que tem!


É impressionante como as pessoas fazem macros mirabolantes pelo Excel, gastam horas fazendo aquilo e tratam como se fosse a minima dos olhos pelo esforço e dedicação como conseguiram fazer um aplicativo vinculado a uma planilha. Mais ainda, o que me deixa ainda mais pasmo é como isso é funcional e pode ser transportado de um computador para o outro, afinal, todos tem Excel assim como Windows e IE.

Bom, o fato é que a coisa fica preta quando vamos pegar uma informação do Excel e jogar no AutoCAD, posso dizer sabiamente que teve um imbecil que fez uma macro em VBA que gera um DXF que pode ser importado para o AutoCAD mas como não encontrei evidências disso na Net não pude traze-loas para este blog de curiosidade.

Estes dias me pediram para dar uma solução que lesse uma série de arquivos de Excel e cada um gerasse um arquivo de AutoCAD com as informações lidas no Excel e salvasse tudo numa pasta para ser impresso e verificado. Inicialmente eu pensei que seri algo simples, mas coisa não é bem assim. O Excel assim como os produtos do pacote Office são blindados com acesso de aplicativos maliciosos assim, ao mesmo tempo que você tem que utilizar a biblioteca deles você também tem que fidelizar o seu aplicativo a versão de dll instaladas do Excel, por exemplo, eu tenho o 2013, que o pacote é o Microsoft Office 14.0 Object Library.

O programa exemplo que vou mostrar aqui puxa apenas o valores do Excel e joga no AutoCAD traçando retas a partir de um ponto de referência, em linhas se chama seção diagonal.

O que foi feito, assim como eu tenho feito em outros programas, e chamar um formulário a partir de um comando no AutoCAD e os botões do formulário "invocarem" de modo assíncrono as funções pela linha de comando do AutoCAD, naturalmente, todas as células do formulários estão declaradas como Public num formulário global da função.


Abaixo segue o código, que dispensa comentários, utilizado o Microsoft Office 14.0 Object Library.

 try  
       {  
         OpenFileDialog openFileDialog1 = new OpenFileDialog();  
         openFileDialog1.InitialDirectory = "c:\\";  
         openFileDialog1.Filter = "xls files (*.xls)|*.xls|All files (*.*)|*.*";  
         openFileDialog1.FilterIndex = 1;  
         openFileDialog1.RestoreDirectory = true;  
         if (openFileDialog1.ShowDialog() != DialogResult.OK)  
           return;  
         String myFile = openFileDialog1.FileName.ToString();  
         List<String> WorksheetsNames = new List<string>();  
         foreach (Microsoft.Office.Interop.Excel.Worksheet wSheet in ActiveWorkbook.Worksheets)  
           WorksheetsNames.Add(wSheet.Name.ToString());  
         Worksheet ActiveWorkSheet = ActiveWorkbook.Worksheets["Autop."];  
         ActiveWorkSheet.Select();  
         //-------------------------------------------------------------------------  
         //Lendo as distâncias  
         Range rng = (Range)ActiveWorkSheet.get_Range(Frm_CADPetor.TextBox_DistanceRange.Text.ToString());  
         List<double> Measurement_Distance = new List<double>(); ;  
         for (int rCnt = 1; rCnt <= rng.Rows.Count; rCnt++)  
           for (int cCnt = 1; cCnt <= rng.Columns.Count; cCnt++)  
             Measurement_Distance.Add((double)(rng.Cells[rCnt, cCnt] as Range).Value2);  
         //-------------------------------------------------------------------------  
         //Lendo A  
         rng = (Range)ActiveWorkSheet.get_Range(Frm_CADPetor.TextBox_SectionA_Range.Text.ToString());  
         List<double> SectionA_Values = new List<double>(); ;  
         for (int rCnt = 1; rCnt <= rng.Rows.Count; rCnt++)  
           for (int cCnt = 1; cCnt <= rng.Columns.Count; cCnt++)  
             SectionA_Values.Add((double)(rng.Cells[rCnt, cCnt] as Range).Value2);  
         //-------------------------------------------------------------------------  
         //Lendo B  
         rng = (Range)ActiveWorkSheet.get_Range(Frm_CADPetor.TextBox_SectionB_Range.Text.ToString());  
         List<double> SectionB_Values = new List<double>(); ;  
         for (int rCnt = 1; rCnt <= rng.Rows.Count; rCnt++)  
           for (int cCnt = 1; cCnt <= rng.Columns.Count; cCnt++)  
             SectionB_Values.Add((double)(rng.Cells[rCnt, cCnt] as Range).Value2);  
         //-------------------------------------------------------------------------  
         //Lendo C  
         rng = (Range)ActiveWorkSheet.get_Range(Frm_CADPetor.TextBox_SectionC_Range.Text.ToString());  
         List<double> SectionC_Values = new List<double>(); ;  
         for (int rCnt = 1; rCnt <= rng.Rows.Count; rCnt++)  
           for (int cCnt = 1; cCnt <= rng.Columns.Count; cCnt++)  
             SectionC_Values.Add((double)(rng.Cells[rCnt, cCnt] as Range).Value2);  
         //-------------------------------------------------------------------------  
         //Lendo D  
         rng = (Range)ActiveWorkSheet.get_Range(Frm_CADPetor.TextBox_SectionD_Range.Text.ToString());  
         List<double> SectionD_Values = new List<double>(); ;  
         for (int rCnt = 1; rCnt <= rng.Rows.Count; rCnt++)  
           for (int cCnt = 1; cCnt <= rng.Columns.Count; cCnt++)  
             SectionD_Values.Add((double)(rng.Cells[rCnt, cCnt] as Range).Value2);  
         //-------------------------------------------------------------------------  
         //Progressiva  
         rng = (Range)ActiveWorkSheet.get_Range(Frm_CADPetor.TextBox_ProgDist.Text.ToString());  
         double Progressive_Distance = (double)(rng.Cells[1, 1] as Range).Value2;  
         //-------------------------------------------------------------------------  
         //Còdigo da Torre  
         rng = (Range)ActiveWorkSheet.get_Range(Frm_CADPetor.TextBox_StructureNumber.Text.ToString());  
         string StructureNumber = (string)(rng.Cells[1, 1] as Range).Value2;  
         Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;  
         Database db = doc.Database;  
         Editor ed = doc.Editor;  
         // Create a point collection to store our vertices  
         Point3dCollection pts = new Point3dCollection();  
         // Set up the selection options  
         // (used for all vertices)  
         PromptPointOptions opt = new PromptPointOptions("\nSelecione um ponto de inserção: ");  
         opt.AllowNone = true;  
         // Get the start point for the polyline  
         PromptPointResult res = ed.GetPoint(opt);  
         Color[] pldvs_color = new Color[] { Color.FromRgb(255, 0, 255), Color.FromRgb(0, 255, 255), Color.FromRgb(0, 255, 0), Color.FromRgb(255, 0, 0) };  
         double[] x = Measurement_Distance.ToArray();  
         for (int j = 1; j <= 4; j++)  
         {  
           double[] y = SectionA_Values.ToArray();  
           if (j == 1)  
           {  
             y = SectionA_Values.ToArray();  
           }  
           else if (j == 2)  
           {  
             y = SectionB_Values.ToArray();  
           }  
           else if (j == 3)  
           {  
             y = SectionC_Values.ToArray();  
           }  
           else if (j == 4)  
           {  
             y = SectionD_Values.ToArray();  
           }  
           double xdir = 1;  
           if (j >= 3)  
           {  
             xdir = -1;  
           }  
           MText mtext = new MText();  
           Polyline pline = new Polyline();  
           pline.AddVertexAt(pline.NumberOfVertices, new Point2d(res.Value.X, res.Value.Y), 0, 0, 0);  
           for (int i = 0; i < y.Length - 1; i++)  
           {  
             pline.AddVertexAt(pline.NumberOfVertices, new Point2d(xdir * x[i] + res.Value.X, y[i] + res.Value.Y - 100), 0, 0, 0);  
           }  
           pline.Color = pldvs_color[j - 1];  
           mtext.Color = pldvs_color[j - 1];  
           mtext.Height = 2.25;  
           pline.LineWeight = LineWeight.LineWeight030;  
           if (j == 1)  
           {  
             mtext.Contents = "A";  
             mtext.Location = new Point3d(res.Value.X + 15, res.Value.Y + 10, 0);  
           }  
           else if (j == 2)  
           {  
             mtext.Contents = "B";  
             mtext.Location = new Point3d(res.Value.X + 15, res.Value.Y + 7.5, 0);  
           }  
           else if (j == 3)  
           {  
             mtext.Contents = "C";  
             mtext.Location = new Point3d(res.Value.X + 15, res.Value.Y + 5, 0);  
           }  
           else if (j == 4)  
           {  
             mtext.Contents = "D";  
             mtext.Location = new Point3d(res.Value.X + 15, res.Value.Y + 2.5, 0);  
           }  
           Transaction tr = db.TransactionManager.StartTransaction();  
           using (tr)  
           {  
             BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);  
             BlockTableRecord btr = (BlockTableRecord)tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite);  
             ObjectId plineId = btr.AppendEntity(pline);  
             tr.AddNewlyCreatedDBObject(pline, true);  
             ObjectId mt = btr.AppendEntity(mtext);  
             tr.AddNewlyCreatedDBObject(mtext, true);  
             tr.Commit();  
             //ed.WriteMessage("\nPolyline entity is: " + plineId.ToString() );  
             ed.Regen();  
           }  
         }  
       }  
       catch  
       {  
       }  


O código é bem simples ele chama a instância do Excel atribui o arquivo de leitura, a partir disso ele mesmo pega a aba selecionada inicialmente e a partir dela ele começa a pegar o Range de células. Diferente do Excel VBA o Excel .NET você pega um Range de células e você TEM QUE saber o que se trata dentro das células, caso contrário ocorre um erro que durante a debugação fecha a aplicação é o VS 2013, tinha feito testes antes e ele também teimava em fechar o VS 2013.

Ainda vou melhorar isso, mas resolvi posta o código para não perde-lo. Existem métodos melhores inclusive que não necessitam de se criar a instância do Excel.

Comentários

  1. Boa Noite

    Preciso de programador de plugins para Autocad. Caso se interesse me encaminhe um e-mail com seu contato. Estamos com um projeto interessante e buscamos parceria para desenvolver. (jeanhenriq@gmail.com)

    ResponderExcluir

Postar um comentário

Postagens mais visitadas deste blog

Numeração Automática no AutoCAD

Sem dúvida esse é uma ferramenta única que fazia falta a tempos e foi introduzida recentemente no AutoCAD, na última década… Em 2013 tinha feito um programa para criar uma bolinhas de numeração automática usando o conceito de Leader eu fazia um controle dos números dos itens na mão mesmo, depois de um tempo resolvi fazer um menuzinho para controlar o conteúdo do número dos bullets, hoje isso não é mais necessário, existe um comando no próprio AutoCAD para isso e faz parte das Ferramentas Expressas do AutoCAD. Gosto de compartilhar ferramentas e dicas que tendem a ser menos conhecidas ou subutilizadas, mas ainda podem fornecer um impulso para sua produtividade e fluxo de trabalho e que eu mesmo me surpreendi quando as encontrei Hoje, quero apresentar outra ferramenta, a numeração automática. Como o nome indica, o comando Numeração automática permite que você adicione automaticamente um número às etiquetas ou texto em um desenho. Vou mostrar como a numeração automática pode ser usada par...

Alterar a cor de fundo do AutoCAD

Eu sou um adepto do fundo preto, tudo que eu posso mudo a cor do fundo para preto. Nas ultimas versões do AutoCAD tenho notado que não é mais o padrão o fundo preto absoluto, é um cinza escuro. As vezes gosto também de mudar a cor do Layout de branco para preto afinal de contas quando trabalhamos com penas e contraste no model space preto, ver um desenho no layout é impossível.  Você pode mudar sua cor de fundo do AutoCAD para a cor que quiser. Definindo cores personalizadas Primeiro, vá para o menu Opções (botão Aplicativo> Opções), selecione a guia Exibição e clique no botão Cores. Agora você deve ver a caixa de diálogo Cores da janela de desenho: Agora você pode atualizar as cores de qualquer elemento da interface. Isso incluí o plano de fundo em qualquer contexto (selecione Model e Layout). Você pode escolher qualquer uma das predefinições, ou você pode escolher a partir de todo o espectro (basta escolher a opção Selecionar Cor ...). Se você não gost...

Unindo blocos em AutoCAD utilizando .NET

Hoje me deparai com uma necessidade de unir blocos com propriedades então resolvi fazer um comando para realizar esses procedimento. A principio esse procedimento não é tão complexo de ser executado individualmente mas por outro lado gostaria também de analisar um pouco melhor as possibilidades de se manipular blocos utilizando o AutoCAD. Abaixo o código que utilizei: using Autodesk.AutoCAD.ApplicationServices ; using Autodesk.AutoCAD.DatabaseServices ; using Autodesk.AutoCAD.EditorInput ; using Autodesk.AutoCAD.Runtime ; using System.Linq ; // This line is not mandatory, but improves loading performances [assembly: CommandClass(typeof(Merging_AutoCAD_blocks.Comandos))] namespace Merging_AutoCAD_blocks { public class Comandos { /// <summary> /// Uni dois ou mais blocos em um unico bloco. /// </summary> [CommandMethod("MERGBLKS")] public static void UnindoBlocos () {...