VBA for Computing Total Length, Area, Volume, Count for every Layers

VBA for Computing Total Length, Area, Volume, Count for every Layers

Anonymous
Not applicable
5,406 Views
17 Replies
Message 1 of 18

VBA for Computing Total Length, Area, Volume, Count for every Layers

Anonymous
Not applicable

Good Day, I would like to request a codes or an accessible files of autocad vba (userform/macro/.dvb/.frm). What I am trying to achieve is a toolbar that allows me to compute values and arrange it in a table per layers. Any files could do, related or not, finished or not, i'll try to get some  ideas/codes/formats how its made, still learning some codes. As for example..

 

I draw many lines,polylines, area/region, volume on autocad with different LAYER name each.

then i'll just drag select all the objects I want to compute, then give me result of the TOTAL LENGTH, TOTAL AREA, TOTAL VOLUME, TOTAL COUNT(separated function) showed in TABLE/listbox per LAYER, then later on i'll try to send it to EXCEL.

 

REQUEST FORMAT.png

I hope you guys could spare some files that is accessible. I'll just try to understand the codes.

thanks

0 Likes
5,407 Views
17 Replies
Replies (17)
Message 2 of 18

grobnik
Collaborator
Collaborator

Hi @Anonymous 

Here below a sample code.

It consist off:

Selecting for each layer the object type and retrive properties, perimeter, area, length.

It's a preliminary, perhaps someone could improve better.

Should be included the table update in the drawing, and in case excel connection.

Bye 

 

Sub Layers_DATA()
Dim LayName() As Variant
Dim ObjectsName() As Variant
Dim LayerSx As AcadLayers
Dim LayerX As AcadLayer
Dim MyObject As AcadEntity
Set LayerSx = ThisDrawing.Layers
Count = 1
Count1 = 1
For Each LayerX In LayerSx
    If LayerX.Name <> "0" And LayerX.Name <> "Defpoints" Then
        ReDim Preserve LayName(Count)
        LayName(Count) = LayerX.Name
        Count = Count + 1
        For Each MyObject In ThisDrawing.ModelSpace
            If MyObject.Layer = LayerX.Name Then
                ReDim Preserve ObjectsName(Count1)
                ObjectsName(Count1) = MyObject.ObjectName
               
                Select Case ObjectsName(Count1)
                    Case "AcDbPolyline"
                        TotalLength = TotalLength + MyObject.Length
                    Case "AcDbLine"
                        TotalLength = TotalLength + MyObject.Length
                    Case "AcDbRegion"
                        TotalPerimeter = TotalPerimeter + MyObject.Perimeter
                        TotalArea = TotalArea + MyObject.Area
                    Case "AcDbCircle"
                        TotalCirc = TotalCirc + MyObject.Circumference
                        TotalDiam = TotalDiam + MyObject.Diameter
                    Case "AcDb3dSolid"
                        Debug.Print "PIPO"
                End Select
                Count1 = Count1 + 1
            End If
        Next
    End If
    'TRANSFER DATA TO EXCEL or to a TABLE and reset data and count for next layer
    
    
    TotalLength = 0
    TotalPerimeter = 0
    TotalArea = 0
    TotalCirc = 0
    TotalDiam = 0
    Count1 = 0
    
Next
End Sub

 

0 Likes
Message 3 of 18

Anonymous
Not applicable

@grobnik

Thanks sir,  Finally I got progress adding the length of objects.

However, it seems it sums up all the lines in drawings regardless of layers. 

How can I separate the results per layers, and use selection instead of automatically adds all objects in drawing.

And to show the result in listbox.

 

I hope someone could give me a little ideas that I could put in puzzle.

 

Thanks again sir. 

0 Likes
Message 4 of 18

grobnik
Collaborator
Collaborator

Hi @Anonymous ,

the code made calculation for each layer, because inside the for next cycle that switch layer.

Before the part of code:

  'TRANSFER DATA TO EXCEL or to a TABLE and reset data and count for next layer
    
    
    TotalLength = 0
    TotalPerimeter = 0
    TotalArea = 0
    TotalCirc = 0
    TotalDiam = 0
    Count1 = 0
    
Next

you already have the possibility to transfer data about:

Layers

Count of object per layer

Length

Area

etc

When all global count will be settle to 0 in the code, means that we are analyzing objects in the next one layer:

See part of code below.

'....
Set LayerSx = ThisDrawing.Layers ' collect all layers in the dwg
Count = 1
Count1 = 1
For Each LayerX In LayerSx ' cycle for each layer into dwg.
    If LayerX.Name <> "0" And LayerX.Name <> "Defpoints" Then 'do not consider special layer including layer 0.
'....

I suggest to transfer data to a Table inside the dwg, or directly to excel.

A listbox or combobox it's more complex, due to you have create a form, and so on.

This part shall be still developed, until now, and it's not completely solved, my focus was retrive data from objects.

I still have some issue with 3d Objects for volume.

I'll keep you updated.

Bye

0 Likes
Message 5 of 18

grobnik
Collaborator
Collaborator

Hi @Anonymous I made some progress, see attached dwg and code.

The procedure creates 4 different tables inside drawing Linear, Area, Volume (I'm still working on), and count of object.

The code should be more or less linear and flexible, the main issue it's to match the object properties with the correct amount. For Example there is a circle object which I considered circumference as Linear data, so added to linear table, and area to Area Table, may be wrong or correct I don't know.

In addition I excluded from count layer 0, Defpoints and AM_CL the last on  related to Construction Line.

If you need you can add or remove more, adding / removing it directly on drawing,

You should check and a give me a feedback.

As you can see from the code the total amount it's made for each layer, the same as before.

Once you run the procedure a group of table will be drawn, so if you made modifications to procedure, before running it again remember to delete the table group placed above yours old one. On the opposite you will have tables overlapped.

 

 

If you want to check attached the code (ZIP FIle of .BAS procedure for VBA) and dwg (saved Autocad 2018)

Bye.

 

Sub Layers_DATA()
Dim LayName() As Variant
Dim ObjectsName() As Variant
Dim LayerSx As AcadLayers
Dim LayerX As AcadLayer
Dim MyObject As AcadEntity

Set LayerSx = ThisDrawing.Layers
LayCount = LayerSx.Count

Dim ptMyTableLinear(0 To 2) As Double
ptMyTableLinear(0) = 3100
ptMyTableLinear(1) = 22000
ptMyTableLinear(2) = 0

Dim ptMyTableArea(0 To 2) As Double
ptMyTableArea(0) = 3100 * 2
ptMyTableArea(1) = 22000
ptMyTableArea(2) = 0

Dim ptMyTableVolume(0 To 2) As Double
ptMyTableVolume(0) = 3100 * 3
ptMyTableVolume(1) = 22000
ptMyTableVolume(2) = 0

Dim ptMyTableTotObj(0 To 2) As Double
ptMyTableTotObj(0) = 3100 * 4
ptMyTableTotObj(1) = 22000
ptMyTableTotObj(2) = 0

Dim MyTableLinear As AcadTable
Dim MyTableArea As AcadTable
Dim MyTableVolume As AcadTable
Dim MyTableTotObj As AcadTable

Dim MyModelSpace As AcadModelSpace
Set MyModelSpace = ThisDrawing.ModelSpace

'AddTable(InsertionPoint, NumRows, NumColumns, RowHeight, ColWidth)
Set MyTableLinear = MyModelSpace.AddTable(ptMyTableLinear, LayCount, 2, 300, 1550)
Set MyTableArea = MyModelSpace.AddTable(ptMyTableArea, LayCount, 2, 300, 1550)
Set MyTableVolume = MyModelSpace.AddTable(ptMyTableVolume, LayCount, 2, 300, 1550)
Set MyTableTotObj = MyModelSpace.AddTable(ptMyTableTotObj, LayCount, 2, 300, 1550)

'object.SetCellValue row, col, val
MyTableLinear.SetCellValue 0, 0, "LINEAR"
MyTableLinear.SetCellValue 1, 0, "LAYERS"
MyTableLinear.SetCellValue 1, 1, "VALUE"

MyTableArea.SetCellValue 0, 0, "AREA"
MyTableArea.SetCellValue 1, 0, "LAYERS"
MyTableArea.SetCellValue 1, 1, "VALUE"

MyTableVolume.SetCellValue 0, 0, "VOLUME"
MyTableVolume.SetCellValue 1, 0, "LAYERS"
MyTableVolume.SetCellValue 1, 1, "VALUE"

MyTableTotObj.SetCellValue 0, 0, "TOT. OBJ."
MyTableTotObj.SetCellValue 1, 0, "LAYERS"
MyTableTotObj.SetCellValue 1, 1, "VALUE"
Row = 2
For Each LayerX In LayerSx
  If LayerX.Name <> "0" And LayerX.Name <> "Defpoints" And LayerX.Name <> "AM_CL" Then
        MyTableLinear.SetCellValue Row, 0, LayerX.Name
        MyTableArea.SetCellValue Row, 0, LayerX.Name
        MyTableVolume.SetCellValue Row, 0, LayerX.Name
        MyTableTotObj.SetCellValue Row, 0, LayerX.Name
        Row = Row + 1
    End If
Next

Count = 1
Count1 = 1
For Each LayerX In LayerSx
    If LayerX.Name <> "0" And LayerX.Name <> "Defpoints" And LayerX.Name <> "AM_CL" Then
        ReDim Preserve LayName(Count)
        LayName(Count) = LayerX.Name
        Count = Count + 1
        For Each MyObject In ThisDrawing.ModelSpace
            If MyObject.Layer = LayerX.Name Then
                ReDim Preserve ObjectsName(Count1)
                ObjectsName(Count1) = MyObject.ObjectName
               
                Select Case ObjectsName(Count1)
                    Case "AcDbPolyline"
                        
                        If MyObject.Closed = True Then
                            TotalArea = TotalArea + MyObject.Area
                            For Row = 2 To LayCount
                                If MyTableArea.GetCellValue(Row, 0) = LayerX.Name Then
                                    MyTableArea.SetCellValue Row, 1, FormatNumber(TotalArea, 2)
                                End If
                            Next Row
                        End If
                            TotalLength = TotalLength + MyObject.Length
                            For Row = 2 To LayCount
                                If MyTableLinear.GetCellValue(Row, 0) = LayerX.Name Then
                                    MyTableLinear.SetCellValue Row, 1, FormatNumber(TotalLength, 2)
                                End If
                            Next Row
                        
                    Case "AcDbLine"
                        TotalLength = TotalLength + MyObject.Length
                        For Row = 2 To LayCount
                            If MyTableLinear.GetCellValue(Row, 0) = LayerX.Name Then
                                MyTableLinear.SetCellValue Row, 1, FormatNumber(TotalLength, 2)
                            End If
                        Next Row

                        
                    Case "AcDbRegion"
                        TotalLength = TotalLength + MyObject.Perimeter
                        For Row = 2 To LayCount
                            If MyTableLinear.GetCellValue(Row, 0) = LayerX.Name Then
                                MyTableLinear.SetCellValue Row, 1, FormatNumber(TotalLength, 2)
                            End If
                        Next Row
                        
                        TotalArea = TotalArea + MyObject.Area
                        For Row = 2 To LayCount
                            If MyTableArea.GetCellValue(Row, 0) = LayerX.Name Then
                                MyTableArea.SetCellValue Row, 1, FormatNumber(TotalArea, 2)
                            End If
                        Next Row
                        
                    Case "AcDbCircle"
                        TotalLength = TotalLength + MyObject.Circumference
                        For Row = 2 To LayCount
                            If MyTableLinear.GetCellValue(Row, 0) = LayerX.Name Then
                                MyTableLinear.SetCellValue Row, 1, FormatNumber(TotalLength, 2)
                            End If
                        Next Row
                        TotalArea = TotalArea + MyObject.Area
                        For Row = 2 To LayCount
                            If MyTableArea.GetCellValue(Row, 0) = LayerX.Name Then
                                MyTableArea.SetCellValue Row, 1, FormatNumber(TotalArea, 2)
                            End If
                        Next Row
                       
                    Case "AcDb3dSolid"
                        Debug.Print "PIPO"
                        
                        
                        
                End Select
                
                For Row = 2 To LayCount
                    If MyTableTotObj.GetCellValue(Row, 0) = LayerX.Name Then
                        MyTableTotObj.SetCellValue Row, 1, FormatNumber(Count1, 2)
                    End If
                Next Row
                Count1 = Count1 + 1
            
            End If
        Next
    End If
    
    TotalLength = 0
    TotalArea = 0
    Count1 = 0
    Row = 2
Next
End Sub

 

 

0 Likes
Message 6 of 18

Anonymous
Not applicable

grobnik

I appreciate the effort sir, the cad file seems broken, it gives me an error "Drawing file is not valid." while I can still open my other files. BTW, i'm using 2021.

I tried to copy and paste the vba codes, some variables not defined, but I added it now

Dim row As Integer
Dim count As Integer
Dim count1 As Integer
Dim TotalArea As Long
Dim TotalLength As Long

it works now,

 

AREA is perfect 

LINEAR is perfect (except it also calculates the edge length of a REGION)<< I get region from exploding 3D/cube

COUNT seems not accurate doesn't count 1 RECTANGLE as an object (if possible, can it count the objects with same shape/object, for example

           Layer1=3 (lines with same length)

           Layer1=2 (rectangle same size)

           Layer2=5 (circle same size)

 

and how can I increase the TEXT height of table, the table size is fine, since I use mm units

Untitled1.jpg

 

Again, thank you for the effort sir.

God Bless

0 Likes
Message 7 of 18

grobnik
Collaborator
Collaborator

Hi @Anonymous ,

I appreciate you tested so in deep, variable could be not declared if you do not insert an Option Explicit inside the code, and on my side there isn't this option, in any case are secondary variable used just in for next loop or for counting.

Concerning the text height you can define by "STYLE" the style of text you want to apply to your global dwg for example "standard", and in the same way it will be applied to Table, as alternative you can set the text height for each cell.

I'll check during the week if I'll have time, and give you a feedback for count.

0 Likes
Message 8 of 18

Tom.LynchKGXNK
Explorer
Explorer

Wow this is really impressive! 

Is there a way you can dump the information straight into excel? 

0 Likes
Message 9 of 18

grobnik
Collaborator
Collaborator

@Tom.LynchKGXNK 

Yes, share a sample dwg with info required to be passed to excel and i'll show you the code.

0 Likes
Message 10 of 18

Tom.LynchKGXNK
Explorer
Explorer

Hi Grobnik

 

Thanks heaps for your help, I've spent so much time trying to figure this out. 

Like the VBA above, I'm trying to output total length of lines, polylines, number of lines, number of polylines, number of blocks, and hatch areas for each layer in the drawing as a csv file.

 

Do you think something like that is possible? 

 

I attached a .dwg that i am currently working on. 

 

Thanks heaps for your help!!

0 Likes
Message 11 of 18

grobnik
Collaborator
Collaborator

Hi @Tom.LynchKGXNK I had a look to your dwg, it's very complex, I can give you some methods for counting mains objects like line polylines blocks, but I guess you have to give me some "filters" for example: If I'll search for blocks perhaps could be counted the referenced blocks but not part of drawing, just to explain better drawing not purged of unused objects.

So if you have a filter for example certain layers, or block name, or line / polyline colours shall be more easy to extract only wanted data.

In the mean time I'll work on it, try to use the code in this post, if you are able to use VBA, just to start evaluating later could be refined.

Bye

0 Likes
Message 12 of 18

grobnik
Collaborator
Collaborator

Hi @Tom.LynchKGXNK here attached the result of shared drawing as table inside the drawing.

Will follow excel transfer instead table into the drawing.

Please look at results and let me know if is covering what you are expecting.

Bye

Message 13 of 18

Tom.LynchKGXNK
Explorer
Explorer

Hi @grobnik

 

That is perfect mate! Exactly what I was trying to do. 

 

I wasn't going to worry about filtering blocks, I was thinking if I can get it to work, I will just assign each block type its own layer and sort it out in excel. 

 

Thanks, heaps, for your help so far! 

 

 

0 Likes
Message 14 of 18

grobnik
Collaborator
Collaborator

@Tom.LynchKGXNK

actually LAYER "0" will be not taken in consideration, it's still used ? shall be considered into the procedure ?

Let me know

0 Likes
Message 15 of 18

Tom.LynchKGXNK
Explorer
Explorer
Hi @grobnik,

I don't need layer "0" but if it's easier to keep it in I'm happy for it to stay.

Thanks again!
Tom
0 Likes
Message 16 of 18

grobnik
Collaborator
Collaborator

@Tom.LynchKGXNK 

Here attached a limited code just for your example, and below the excel results.

You have as first step add Excel reference to VBA project.

Use on Visual basic editor Autocad Application the menu command tools, and then references, flag the Excel Library.

Showed number after Microsoft Excel XX.X Object Library it's depend from Excel release you have installed in your machine.

There is in addition a small routine that could help you to discover several object types.

I hope you know how to manage the VBA project.

 

Let me know.

grobnik_0-1675918225295.png

 

LAYERSPOLYLINES TOTAL LENGHTPOLYLINES TOTAL AREALINES TOTAL LENGHTTOTAL BLOCKS
064,1527,60  
ZTitleBlock    
batter top1.256,17   
bitumen edge    
pathway4.621,13398,89  
kerb back721,63291,07  
kerb lip2.748,11513,14  
kerb SM3    
stormwater catchpit    
stormwater manhole    
table drain invert    
stormwater headwall    
building    
XELEC OH    
landscape    
driveway concrete hatch    
surface toe    
stormwater pipe    
stormwater pit    
stormwater culvert    
fence line    
fence gate    
electricity pillar    
driveway    
creek bank toe    
subsoil rd    
saw cut bdy    
earthwork drain invert    
earthwork drain edge    
edge of verge    
bridge abutment    
bridge deck    
retaining wall top    
stormwater gully unit    
RS01 DESIGN    
Extra DS    
RS05 DESIGN    
RS06 DESIGN    
stormwater gully unit setout    
BREAKLINE    
KR19 DESIGN    
parks garden edge    
build line    
electricity pole text    
MF33 DESIGN    
rock prot    
ACO hatch    
invert drain line    
mowing strip    
TERRACE HATCH    
RST01 DESIGN    
Culvert RS01 14 558    
Culvert RS01 14 558 IO    

 

0 Likes
Message 17 of 18

Tom.LynchKGXNK
Explorer
Explorer
Hi @grobnik
 
 

 

This is really impressive, this is exactly what I have been trying to do! 

 

Thanks heaps for setting this up!!!

 

Cheers

Tom

0 Likes
Message 18 of 18

grobnik
Collaborator
Collaborator
Thank you, it's just a starting point, you can add what do you need to count, or summarize or something else.
Scope of project is give you a tools and the path for extracting data from your dwg. I don0t know in deep your requirements.

Let me know if you need more support.
Bye
0 Likes