Pular para o conteúdo principal

Criando uma tabela baseada em desenhos do AutoCAD usando .NET

A muito tempo que utilizo tabelas dentro de desenhos DWG. As vezes preciso converter uma tabela em Excel para o AutoCAD o que por vezes é chato e as vezes fica muito ruim principalmente porque as tabelas não respeitam os tipos de fonte do desenho etc...

Estava buscando na internet formas alternativas de o faze-lo e encontrei no blog do Kean Walmsley um post com este código que envolve duas coisas que precisarei: (i) manipulação de múltiplos documentos DWG com importação e (ii) manipulação de tabelas e construção dinâmica baseadas em código.

Aqui está o código em C#:

using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.Windows;
using System.IO;
using System.Linq;

namespace Recursos_Blocos
{
    public class Comandos_Blocos
    {
        [CommandMethod("LISTAR_BLOCOS_DESENHOS")]
        public void ListarDesenhosDosBlocos()
        {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;

            // Selecionar os desenhos a serem listados na tabela
            OpenFileDialog ofd = new OpenFileDialog(
                "Selecione os desenhos a serem analisados",
                null,
                "dwg",
                "Desenhos para Importar",
                OpenFileDialog.OpenFileDialogFlags.AllowMultiple
              );

            System.Windows.Forms.DialogResult dr = ofd.ShowDialog();

            // Trata a entrada vazia
            if (dr != System.Windows.Forms.DialogResult.OK)
                return;

            // Separa a lista de Nomes dos desenhos Selecionados
            string[] names = ofd.GetFilenames();
            ed.WriteMessage("\n{0} arquivos selecionados.", names.Length);

            // Começa a processar a tabela em função dos documentos selecionados.
            //Será criada uma tabela dentro do documento DWG usando os recusros
            //de tabela do próprio AutoCAD.
            if (names.Length > 0)
            {
                int numRows, numCols;

                // Trata separadamente o caso do 1x1
                if (names.Length == 1)
                {
                    numRows = 1;
                    numCols = 1;
                }
                else
                {
                    PromptIntegerOptions opts = new PromptIntegerOptions(
                        "\nInforme o número de colunas: ");

                    opts.LowerLimit = 1;
                    opts.UpperLimit = names.Length;
                    opts.DefaultValue = 1;
                    opts.UseDefaultValue = true;

                    PromptIntegerResult pir = ed.GetInteger(opts);

                    //Se não entrar com valor nenhum sai do código
                    if (pir.Status != PromptStatus.OK)
                        return;

                    bool fromTop = true;
                    bool sort = false;

                    // And the insertion point of the table
                    PromptPointResult pr = ed.GetPoint("\nIndique o ponto de insersão da Tabela: ");

                    //Se selecionar o ponto, então continue...
                    if (pr.Status == PromptStatus.OK)
                    {
                        // Inicia a transferência de açõs com o documento
                        Transaction tr = doc.TransactionManager.StartTransaction();

                        using (tr)
                        {
                            // Determina o tamanho da célula
                            const int cellWidth = 3;
                            const int cellHeight = 3;

                            // Cria o objeto tabela
                            Table tb = new Table();
                            tb.TableStyle = db.Tablestyle;

                            // Claculando o numero de colunas e linhas
                            numCols = pir.Value;
                            numRows = (names.Length / numCols) + 1;

                            // Adiciona as colinas e linhas no objeto da 
                            //tabela.
                            if (numCols > 0)
                            {
                                tb.InsertColumns(1, cellWidth, numCols);
                            }
                            if (numRows > 0)
                            {
                                tb.InsertRows(1, cellHeight, numRows);
                            }

                            // é necessário deletar o elemento linha coluna 
                            //default que já vem como a tabela.
                            tb.DeleteRows(0, 1);
                            tb.DeleteColumns(0, 1);

                            tb.Position = pr.Value;

                            if (sort)
                            {
                                names = names.OrderBy(x => x).ToArray<string>();
                            }

                            // procura os blocos e faz a leitura
                            for (int i = 0; i < names.Length; i++)
                            {
                                string blockName = "";

                                try
                                {
                                    //Busca os dados e pelo Database.
                                    //Sempre da erro então precisa necessariamente de try 
                                    //casdo não tenha bloco nenhum no desenho.
                                    using (Database src = new Database(false, true))
                                    {
                                        // Lendo o DWG
                                        src.ReadDwgFile(names[i], FileShare.Read, true, "");

                                        blockName = Path.GetFileNameWithoutExtension(names[i]);

                                        // Verifique se ele funciona como um dwg de bloco
                                        // *** Aqui pode ocorrer uma violação *** por isso
                                        // o try catch
                                        SymbolUtilityServices.ValidateSymbolName(
                                          blockName, false
                                        );

                                        // Inseirndo o bloco no db do projeto.
                                        ObjectId blockId = db.Insert(blockName, src, false);

                                        // Calcula o tamanho da tabela novamente.
                                        int row =
                                          (fromTop ?
                                            i / numCols :
                                            numRows - (i / numCols + 1)
                                          );

                                        // a coluna continua do mesmo tamanho
                                        int col = i % numCols;

                                        // Insere a block reference na posição da tabela.
                                        Cell cell = tb.Cells[row, col];
                                        cell.Contents.InsertAt(0);
                                        cell.Contents[0].BlockTableRecordId =
                                           blockId;
                                    }
                                }
                                catch (System.Exception ex)
                                {
                                    ed.WriteMessage("\nOcorreu uma violação \"{0}\": {1}",blockName, ex.Message);
                                }
                            }
                            tb.GenerateLayout();

                            // Coloca a tabela no desenho
                            BlockTable bt = (BlockTable)tr.GetObject(
                                doc.Database.BlockTableId, OpenMode.ForRead);

                            BlockTableRecord btr =
                              (BlockTableRecord)tr.GetObject(
                                  bt[BlockTableRecord.ModelSpace],OpenMode.ForWrite);
                            
                            btr.AppendEntity(tb);
                            tr.AddNewlyCreatedDBObject(tb, true);
                            tr.Commit();
                        }
                    }
                }
            }
        }
    }

}


Esse código faz é pegar todos os blocos existentes em múltiplos DWG’s e coloca-los dentro de uma tabela no desenho ativo do AutoCAD. Isso é muito legal quando você cria diversos blocos de objetos e precisa ao final listar todos que foram utilizados e criar uma legenda.

Nunca precisei disso diretamente, mas poderia ter sido útil no passado...

A utilização do ed.GetInteger()

Esse recurso permite que você retorne um numero interior do prompt de comando já trabalhado, precisa utilizar algum recurso como TryParse etc.

ed.GetPoint()

Outro recurso é a seleção de um ponto na tela para inserção da tabela com o ed.GetPoint(). Você pode perguntar na tela por um ponto de inserção.

AutoCAD Table

Depois temos o objeto Table. A tabela do AutoCAD ela já vem com algumas linhas e colunas então se você simplesmente ir acrescentando sempre ficará as linhas iniciais vazias.
Muitos recursos podem ser “tabelizados” como importar um CSV ou até mesmo uma tabela tabulada em uma caixa de texto.

Por fim se utiliza o recurso ReadDwgFile. Essa função permite ler um arquivo DWG sem precisar abri-lo o que é fantástico porque dá um dinamismo muito grande quando se opera com documentos pesados ou com imagens de Raster.

O aspecto da função é este, quando você executa se abre uma janela de seleção de arquivos.


Depois é solicitado o numero de colunas depois o ponto de inserção.



Por fim a tabela é criada na tela com o conteúdo dos documentos. Nesse caso peguei algumas famílias de blocos exemplo que já estão contidos no AutoCAD. Note que a tabela contém uma entrada que é um bloco como se fosse um DWG.


Isso poderia modernizar muita daquelas legendas que são explodidas para não entrarem nas contagens dos blocos do documento.

Veja um vídeo exemplo de utilização:

Espero que esse código seja útil, até a próxima.

Código em Visual Studio 2019: Download.

Comentários

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 () {...