Changing hatch colors by an Excel table using VBA in AutoCAD

Changing hatch colors by an Excel table using VBA in AutoCAD

Anonymous
Not applicable
4,840 Views
8 Replies
Message 1 of 9

Changing hatch colors by an Excel table using VBA in AutoCAD

Anonymous
Not applicable

Hello,

 

I want to make a map with 16 different plots (A1 to D4) in AutoCAD. Every plot in this map is connected to an excel file, where is some information listed (area, height, year, type) per plot. This map need to be dynamic, so by chosing what to see (for instance: area), the color of the parcels needs to change according to the value per plot (for instance: 12 m2 = yellow, 24 m2  = orange, 48 m2 = red). The two files I am using are send with it.

 

My question is: does anyone know how to program this in VBA in AutoCAD. The shape of the plots I want to draw on my own (hatching each plot is also no problem), and somehow I need to name each plot (hatch). But how can I name the plots (hatches) and change the colour per plot (hatch) in VBA?

 

These files are two sample files to make the question easier. The files I am using have 1600 different plots.

 

Thank for helping!

0 Likes
Accepted solutions (1)
4,841 Views
8 Replies
Replies (8)
Message 2 of 9

Hallex
Advisor
Advisor

Add this code in AutoCAD VBA editor,

(Excel file must be open)

 

Option Explicit

Public Sub TestColorMaps()

Dim ExcelApp As Excel.Application
Dim xlBook As Excel.Workbook
Dim xlSheet As Excel.Worksheet
Dim xlRange As Excel.Range
Set ExcelApp = GetObject(, "Excel.Application")

Set xlBook = ExcelApp.ActiveWorkbook
Set xlSheet = xlBook.Worksheets(1)
xlSheet.Activate
Set xlSheet = ExcelApp.ActiveSheet
Set xlRange = xlSheet.Range("A2:E17")
Dim res As Variant
res = LookupInRange(xlRange)
xlBook.Close False
Set xlBook = Nothing
ExcelApp.Quit
Set ExcelApp = Nothing
DoEvents

    Dim map As String
    map = InputBox("Enter map label:", "Lookup Color", "A1")
    Dim color As String
    color = LookupItem(res, map)
    MsgBox "Found color:   " & color & vbCr & _
    " do your rest work in AutoCAD"
            
End Sub
Private Function LookupInRange(rng As Excel.Range) As Variant
    Dim color As String
    Dim arr(), i

    ' get range value, headers omitted
    arr = rng.Value
    ReDim res(0 To UBound(arr) - 1, 0 To 1)
          For i = LBound(arr) To UBound(arr)
                res(i - 1, 0) = arr(i, 1): res(i - 1, 1) = arr(i, 2)
          Next i
    LookupInRange = res
 End Function
 
Private Function LookupItem(arr As Variant, map As String) As String
    Dim color As String
    Dim i
    Dim ye As Boolean
    ye = False
    color = ""
    ' lookup in the first column
    For i = LBound(arr) To UBound(arr)
    If arr(i, 0) = map Then
    ye = True
    color = arr(i, 1)
    Exit For
    End If
        Next i
        
    LookupItem = color
    
 End Function

 

_____________________________________
C6309D9E0751D165D0934D0621DFF27919
0 Likes
Message 3 of 9

Anonymous
Not applicable

Thanks for helping me!

 

I don't understand every part of the code, but most of it I do.

 

But will this code only give me a cell value from Excel? My main question is to make hatches with different colour (or to change the colour of excisting hatches), with the values given by the Excel sheet.

0 Likes
Message 4 of 9

norman.yuan
Mentor
Mentor

I am not sure what exactly do you mean by "name each hatch". Do you want to run some code after the hatch being drawn to identify the hatch? Can you just identify it by its colour, its area? Or, since you only have 16 hatches, can you place each on its one layer, so that you can use layer to identiy the hatch?

 

If you have to "label" a hatch in some way, you may consider to embed a piece of XData with ID information to each hatch. Then later you can identify the hatch by reading the attached XData.

 

As for set/change hatch color, you simply set AcadHatch.TrueColor property to desired color (determined by data read from Excel sheet, in your case). Something like:

 

    Dim color As AcadAcCmColor
    Set color = AcadApplication.GetInterfaceObject("AutoCAD.AcCmColor.18")
    Call color.SetRGB(80, 100, 244)

    ''Assume you have already obtained a AcadHatch object

    myHatch.TrueColor=color

Norman Yuan

Drive CAD With Code

EESignature

Message 5 of 9

Anonymous
Not applicable

In this example I have 16 hatches, in real it are 1600. So naming layers is too much work then.

 

Many hatches will also have the same size and colour, so identifying by that specifications is impossible.

 

I indeed want to label each square (or hatch) somehow. How can you attach the XData and read it with VBA? Seems the sollution.

 

The colour part was already working, but thanks for it 🙂

0 Likes
Message 6 of 9

norman.yuan
Mentor
Mentor

AcadEntity/AcadHatch object has a pair of methods: GetXData() and SetXData(). In AutoCAD VBA Editor, open Object Browser, select AcadEntity or AcadHatch, highligh GetXData/SetXData, then click "?" on the Object Browser window. This will lead you to the help document for these 2 methods and there is a link pointing to ready-to-use sample code of using these 2 methods.

Norman Yuan

Drive CAD With Code

EESignature

0 Likes
Message 7 of 9

Anonymous
Not applicable

Interesting to set information to an object. Didn't knew it was possible in AutoCAD. But if I set for each of the 16 hatches different XData, is it possible to call an object by the XData and then change the color?

0 Likes
Message 8 of 9

norman.yuan
Mentor
Mentor
Accepted solution

The is what AcadEntity.GetXdata() method is for.

 

Say, for each Hatch, you embeded a piece text as its untigue name/ID when you read data from Excel and draw the hatch. Later you can use code to select all Hatch with XData embeded (with the same registered application name, of course). You can use XData's application name as SelectionSet filter to select the hatches iin interest. Then you loop through each selected entity, call getXData() against each entity and then test the embeded name/ID. This how you idetify the hatch.

Norman Yuan

Drive CAD With Code

EESignature

Message 9 of 9

Anonymous
Not applicable

Both of you thanks a lot! With your information and a lot of other forums I managed to make the script.

 

I made one to select hatches and set XData to it and one to colour the hatches by the given columnname existing in Excel.

 

The hatch picker:

Sub PickObject()
    Dim i
    For i = 0 To 15
        'Roep de selectionset op
        Dim ssOne As AcadSelectionSet
        Set ssOne = SelectOnlyOnScreen
        
        'Kijk of er wel één kavel is geselecteerd
        If ssOne.Count = 0 Then
            MsgBox "Afsluiten", , "Object"
            Exit For
        ElseIf ssOne.Count = 1 Then
            'Dim de geselecteerde hatch
            Dim hatchObject As AcadHatch
            Set hatchObject = ssOne.item(0)
                        
            'Geef de dim een gekozen naam
            Dim plotName As String
            plotName = InputBox("Geef de naam van de kavel:", "Kavelnaam", "A1")
            Dim xdatatype(0 To 1) As Integer
            Dim xdatavalue(0 To 1) As Variant
            xdatatype(0) = 1001
            xdatatype(1) = 1000
            xdatavalue(0) = "Kavel"
            xdatavalue(1) = plotName
            hatchObject.SetXData xdatatype, xdatavalue
            Dim xdatatyperet As Variant
        Else
            MsgBox "Selecteer één object", , "Object"
            i = i - 1
        End If
    Next i
End Sub

Public Function SelectOnlyOnScreen() As AcadSelectionSet
    'Maak de selecionset aan
    Dim ssOne As AcadSelectionSet
    Dim ssAll As AcadSelectionSets
    Set ssAll = ThisDrawing.SelectionSets
    For Each ssOne In ssAll
        If ssOne.Name = "Plot" Then
            'Leeg en verwijder de selectionset
            ssOne.Clear
            ssOne.Delete
            Set ssOne = Nothing
            Exit For
        End If
    Next
    Set ssOne = ThisDrawing.SelectionSets.Add("Plot")
    
    'Kies een object voor de selectionset
    Dim intType(0) As Integer
    Dim varData(0) As Variant
    intType(0) = 0 '0 = geen voorwaarden aan het type
    varData(0) = "HATCH" 'HATCH = selecteer alleen hatchdata
    ssOne.SelectOnScreen intType, varData
    Set SelectOnlyOnScreen = ssOne
End Function

 

The hatch colouring (RGB colours need to be put as text in the Excel next to the desired column):

'Tools -> References -> Microsoft Excel 14.0 Object Library

'Excel moet geopend zijn
'Geef de range van de worksheet op
'Geef het aantal kolommen in de lookup functies

Option Explicit
 
Dim xlApp As Excel.Application
Dim xlBook As Excel.Workbook
Dim xlSheet As Excel.Worksheet
Dim xlRange As Excel.Range
Dim acSpace As AcadModelSpace
Dim totalColumns As Integer
Dim totalRows As Integer
Dim presentColumn As Integer
 
Function ExcelOpen()
    'Deze functie opent Excel
    Dim xlObject As Object
    Set xlObject = GetObject("D:\School\TU Delft\Master 2\AR2A010 Architectural History Thesis\4 Products\2 Farms\2 Test\Test (3).xlsx")
    xlObject.Application.Visible = True
    xlObject.Parent.Windows(1).Visible = True
End Function

Function ExcelConnect()
    'Deze functie maakt de verbinding tussen AutoCAD en Excel
    On Error Resume Next
            
    Set xlApp = GetObject(, "Excel.Application")
    Set xlBook = xlApp.ActiveWorkbook
    Set xlSheet = xlBook.Worksheets(1)
    xlSheet.Activate
    Set xlSheet = xlApp.ActiveSheet
    Set xlRange = xlSheet.Range("A1:I17")

    If Err Then
        Err.Clear
        Set xlApp = CreateObject("Excel.Application")
        xlApp.Visible = True
        If Err Then
            MsgBox Err.Description
            Exit Function
        End If
    End If
End Function
 
Function ExcelClose()
    'Deze functie sluit Excel
    xlBook.Close False
    Set xlBook = Nothing
    xlApp.Quit
    Set xlApp = Nothing
    DoEvents
End Function
Function SetColor(celValue As Variant) On Error Resume Next 'Maak de selectionset aan Dim ssOne As AcadSelectionSet Dim ssAll As AcadSelectionSets Set ssAll = ThisDrawing.SelectionSets For Each ssOne In ssAll If ssOne.Name = "AllEntities" Then 'Als de naam van de selectionset al bestaat 'Leeg en verwijder de selectionset ssOne.Clear ssOne.Delete Set ssOne = Nothing Exit For End If Next Set ssOne = ThisDrawing.SelectionSets.Add("AllEntities") 'Geef de naam aan de selectionset 'Voeg alle hatches aan de selectionset toe Dim intGpCode(0) As Integer Dim varDataValue(0) As Variant intGpCode(0) = 0 '0 = geen voorwaarden aan de gpcode varDataValue(0) = "HATCH" 'HATCH = selecteer alleen hatchdatavalues ssOne.Select acSelectionSetAll, , , intGpCode, varDataValue 'Ga alle hatches in de selectionset af op zoek naar degenen met de juiste naam Dim ssObject As AcadHatch Dim varXDataType As Variant Dim varXDataValue As Variant Dim msg As String 'Maak een string met alle objecten in de selectionset msg = vbCrLf 'Start met een enter Dim color As AcadAcCmColor Set color = AcadApplication.GetInterfaceObject("AutoCAD.AcCmColor.19") '19 is voor AutoCAD 2013 For Each ssObject In ssOne 'Kijk per kavelnummer in de rijtitel in de Excelsheet of deze hetzelfde is als het kavelnummer van de hatch in AutoCAD Dim plotType As String Dim colorValue As String Dim i As Integer For i = 1 To totalRows 'Geef het bereik van de rijen op plotType = celValue(i, 0) colorValue = celValue(i, presentColumn + 1) 'Leest de cel met rij i en de huidige kolom, "+ 1" om de kleurwaarde te krijgen Dim colorSplit As Variant colorSplit = Split(colorValue, ",") 'Splits de cel in drie waarden op (kleur) ssObject.GetXData "Kavel", varXDataType, varXDataValue If varXDataValue(1) = plotType Then 'De eerste waarde (0) is "Kavel", de tweede waarde (1) is het kavelnummer 'Geef een kleur aan de hatch Call color.SetRGB(colorSplit(0), colorSplit(1), colorSplit(2)) 'Gebruikt de drie waarden om een kleur te maken ssObject.TrueColor = color ssObject.Evaluate 'MsgBox varXDataValue(1) 'Laat zien welke kavel is ingekleurd Exit For End If Next msg = msg & vbCrLf & varXDataValue(1) 'Doet een enter en geeft de naam van het object 'Hergenereer het actieve scherm ThisDrawing.Regen acActiveViewport Next ssObject 'MsgBox "De selectionset bevat: " & msg 'Laat zien wat er in de selectionset zit End Function Private Function LookupColumn(rng As Excel.Range) As Variant Dim arr() arr = rng.Value 'De verschillende rijen gesommeerd in een array ReDim res(1 To totalColumns) 'Geeft het kolombereik van de dim op 'Geef waarden aan het bereik Dim i For i = 2 To totalColumns + 1 'Voor de tweede kolom tot de laatste (startwaarde is 1) res(i - 1) = arr(1, i) 'Onthoudt alle kolomtitels Next i 'Dim msg As String 'msg = "0" & vbCrLf & "totalColumns" 'MsgBox msg 'Controleer de lengte van de array LookupColumn = res End Function Private Function LookupInRange(rng As Excel.Range, column As Integer) As Variant Dim arr() arr = rng.Value 'De verschillende rijen gesommeerd in een array totalRows = UBound(arr) ReDim res(0 To totalRows, 0 To totalColumns) 'Geeft het rij- en kolombereik van de dim op 'Geef waarden aan het bereik Dim i For i = LBound(arr) + 1 To UBound(arr) 'Voor de eerste rij tot de laatste (startwaarde is 1) res(i - 1, 0) = arr(i, 1) 'Onthoudt alle rijtitels res(i - 1, column + 1) = arr(i, column + 2) 'Onthoudt alle kleuren voor de gekozen kolom Next i 'Dim msg As String 'msg = LBound(arr) & vbCrLf & UBound(arr) 'MsgBox msg 'Controleer de lengte van de array LookupInRange = res End Function Sub ExcelToAcad() 'De Excellink maken ExcelConnect 'Geef het aantal kolommen totalColumns = 8 'Deze waarde geven aan de hand van de Excelsheet 'Kies het gewenste type kaart Dim columnName As Variant columnName = LookupColumn(xlRange) Dim mapType As String mapType = InputBox("Kies het gewenste type kaart:", "Kaarttype", "Oppervlakte") 'Geef de opgegeven kolomnaam door aan de bijbehorende kolom Dim i As Integer For i = 1 To totalColumns 'Het bereik van de kolommen If columnName(i) = mapType Then mapType = columnName(i) presentColumn = i Exit For End If Next 'MsgBox columnName(i) 'Kijk of de "columnName" ook de "mapType" is 'Haal de celkleuren die bij de kolom horen op Dim celValue As Variant celValue = LookupInRange(xlRange, i) 'MsgBox celValue(1, i + 1) 'Lees een cel (startwaarden zijn 0 (dus rij- en kolomtitels), "+ 1" om de kleurwaarde te krijgen) 'Maak een hatch met de gegeven celdata SetColor celValue 'Maak de hatch 'Hergenereer het actieve scherm ThisDrawing.Regen acActiveViewport End Sub

 

It's not the most perfect code, but it works. I will spend some more hours to make the code smarter.

0 Likes