|
| 1 | +--- |
| 2 | +title: How to Extract Model Data from ETABS to Excel Using VBA |
| 3 | +description: Learn to use the ETABS API to extract model data to Excel |
| 4 | +date: 17-08-2025 |
| 5 | +categories: [VBA, VBA-ETABS] |
| 6 | +tag: [excel, etabs, vba, how to] |
| 7 | +image: /assets/images/etabs/excel-vba-etabs-extract-results.webp |
| 8 | +--- |
| 9 | + |
| 10 | +## Overview |
| 11 | +- In this tutorial, I'll show you how to extract data from an ETABS model using Excel VBA. |
| 12 | +- Why automate this process? |
| 13 | + - You can use this approach together with your results extraction code or model generation. |
| 14 | + - Integrate your model with your design sheet. |
| 15 | +- I am assuming that: |
| 16 | + - You have basic knowledge of VBA and know how to add modules and create new subs. |
| 17 | + - You’re familiar with ETABS and know how to check results manually to compare them with the code output. |
| 18 | + |
| 19 | +## Setup |
| 20 | +- We are going to use two files: |
| 21 | +- ETABS Model: |
| 22 | + - Create a simple ETABS model with a 4x4 grid and 5m spacing, 4 stories. |
| 23 | + - Assign elements: Beam, Column, Slab, and supports. |
| 24 | + - Apply Loads and Load Combinations: Dead Load, Live Load, Floor Load, Wall Load. |
| 25 | +- Excel: |
| 26 | + - Create a macro-enabled Excel file. |
| 27 | + - We are going to print all results in the active sheet, column A. |
| 28 | + - Use the sample code below to print your output. |
| 29 | + |
| 30 | + ```visualbasic |
| 31 | + Sub GetResults() |
| 32 | + 'Clear All Previous Results |
| 33 | + ActiveSheet.Range("A1").CurrentRegion.ClearContents |
| 34 | +
|
| 35 | + 'You can print your output using GetNextCell() Function |
| 36 | + GetNextCell().Value = "Hello, My Name is Vivek" |
| 37 | + GetNextCell().Value = "This is a demo for ETABS API using Excel VBA" |
| 38 | + End Sub |
| 39 | +
|
| 40 | + ' Function to get the next empty cell in column A |
| 41 | + Private Function GetNextCell() As Range |
| 42 | + If ActiveSheet.Range("A1").CurrentRegion.Rows.Count = 1 And IsEmpty(ActiveSheet.Range("A1")) Then |
| 43 | + Set GetNextCell = ActiveSheet.Range("A1") |
| 44 | + Else |
| 45 | + Set GetNextCell = ActiveSheet.Cells(ActiveSheet.Range("A1").CurrentRegion.Rows.Count + 1, 1) |
| 46 | + End If |
| 47 | + End Function |
| 48 | + ``` |
| 49 | +
|
| 50 | +## Extract Model Data |
| 51 | +
|
| 52 | +#### Link Excel with ETABS using VBA |
| 53 | +- First, you have to add a reference for the ETABS API: |
| 54 | + - Open the VBA Editor > Tools > References Dialog. |
| 55 | + - Find `ETABS Application Programming Interface (API) v1` and make sure it's checked. |
| 56 | +
|
| 57 | +> I am using ETABS v22, but this code should work for ETABS version 18 and above. |
| 58 | +> For older versions, you have to add the reference `ETABS v16 Application Programming Interface (API)` (version specific to your ETABS). |
| 59 | +{: .prompt-info } |
| 60 | +
|
| 61 | +```visualbasic |
| 62 | +Sub GetResults() |
| 63 | + 'Clear All Previous Results |
| 64 | + ActiveSheet.Range("A1").CurrentRegion.ClearContents |
| 65 | +
|
| 66 | + 'Get ETABS API Object |
| 67 | + Dim etApp As ETABSv1.cOAPI |
| 68 | + Set etApp = GetObject(, "CSI.ETABS.API.ETABSObject") |
| 69 | +
|
| 70 | + 'Get ETAB Model, this is also compatible with ETABS |
| 71 | + Dim etModel As ETABSv1.cSapModel |
| 72 | + Set etModel = etApp.sapModel |
| 73 | +
|
| 74 | + 'Commonly Used Variables |
| 75 | + 'Using Long types instead of Integer to use this with OpenSTAAD |
| 76 | + Dim i As Long, j As Long |
| 77 | + Dim nodeId As Long, beamId As Long, loadCaseName As String |
| 78 | +
|
| 79 | + '<<< Add Remaining Code Here >>> |
| 80 | +End Sub |
| 81 | +``` |
| 82 | + |
| 83 | +#### Load Patterns |
| 84 | +```visualbasic |
| 85 | +'Get list of all load patterns |
| 86 | +Dim numberOfLoadPatterns As Long, LoadPatterns() As String |
| 87 | +etModel.LoadPatterns.GetNameList numberOfLoadPatterns, LoadPatterns |
| 88 | +
|
| 89 | +'Loop through all load patterns and print load pattern name |
| 90 | +For i = 0 To numberOfLoadPatterns - 1 |
| 91 | + GetNextCell().Value = LoadPatterns(i) |
| 92 | +Next i |
| 93 | +``` |
| 94 | +#### Load Combinations |
| 95 | +```visualbasic |
| 96 | +'Get list of all load combinations |
| 97 | +Dim numberOfLoadCombinations As Long, LoadCombinations() As String |
| 98 | +etModel.RespCombo.GetNameList numberOfLoadCombinations, LoadCombinations |
| 99 | +
|
| 100 | +'Loop through all load combinations and print load combination name |
| 101 | +For i = 0 To numberOfLoadCombinations - 1 |
| 102 | + GetNextCell().Value = LoadCombinations(i) |
| 103 | +Next i |
| 104 | +``` |
| 105 | + |
| 106 | +#### Story Data |
| 107 | +Get the number and names of all stories: |
| 108 | +```visualbasic |
| 109 | +'Get All story data |
| 110 | +Dim NumberOfStories As Long, StoryNames() As String |
| 111 | +etModel.SapModel.GetStoryList NumberOfStories, StoryNames |
| 112 | +
|
| 113 | +'Loop through all stories and print story name |
| 114 | +For i = 0 To NumberOfStories - 1 |
| 115 | + GetNextCell().Value = StoryNames(i) |
| 116 | +Next i |
| 117 | +``` |
| 118 | +Get story data with each story name, elevation, and height |
| 119 | +```visualbasic |
| 120 | +'Get All story data |
| 121 | +Dim BaseElevation As Double |
| 122 | +Dim NumberStories As Long |
| 123 | +Dim StoryNames() As String |
| 124 | +Dim StoryElevations() As Double |
| 125 | +Dim StoryHeights() As Double |
| 126 | +Dim IsMasterStory() As Boolean |
| 127 | +Dim SimilarToStory() As String |
| 128 | +Dim SpliceAbove() As Boolean |
| 129 | +Dim SpliceHeight() As Double |
| 130 | +Dim color() As Long |
| 131 | +
|
| 132 | +etModel.Story.GetStories_2 BaseElevation, NumberStories, StoryNames, StoryElevations, StoryHeights, IsMasterStory, SimilarToStory, SpliceAbove, SpliceHeight, color |
| 133 | +
|
| 134 | +'Print all story data |
| 135 | +For i = 0 To NumberStories - 1 |
| 136 | + GetNextCell().Value = StoryNames(i) ' name |
| 137 | + GetNextCell().Value = StoryElevations(i) ' elevation |
| 138 | + GetNextCell().Value = StoryHeights(i) ' height |
| 139 | +Next i |
| 140 | +``` |
| 141 | +#### Joints |
| 142 | +```visualbasic |
| 143 | +'Get All Joint Node Id for Base Story |
| 144 | +Dim NumberOfJointNodes As Long, JointNodeNames() As String |
| 145 | +etModel.PointObj.GetNameListOnStory "Base", NumberOfJointNodes, JointNodeNames |
| 146 | +
|
| 147 | +'Loop through all joint nodes and print joint node name |
| 148 | +For i = 0 To NumberOfJointNodes - 1 |
| 149 | + GetNextCell().Value = JointNodeNames(i) |
| 150 | +Next i |
| 151 | +``` |
| 152 | +#### Frame Elements |
| 153 | +Get all frame element IDs |
| 154 | +```visualbasic |
| 155 | +'Get All Frame Objects |
| 156 | +Dim numberOfFrameElements As Long, frameElements() As String |
| 157 | +
|
| 158 | +'Get all frame object names |
| 159 | +etModel.FrameObj.GetNameList numberOfFrameElements, frameElements |
| 160 | +
|
| 161 | +'Loop through all object and print their IDs |
| 162 | +For i = 0 To numberOfFrameElements - 1 |
| 163 | + GetNextCell().Value = frameElements(i) |
| 164 | +Next i |
| 165 | +``` |
| 166 | + |
| 167 | +Get column elements |
| 168 | +```visualbasic |
| 169 | +'Get All Frame Objects |
| 170 | +Dim numberOfFrameElements As Long, frameElements() As String |
| 171 | +Dim frameType As eFrameDesignOrientation |
| 172 | +
|
| 173 | +'Get all frame object names |
| 174 | +etModel.FrameObj.GetNameList numberOfFrameElements, frameElements |
| 175 | +
|
| 176 | +'Loop through all object and print their IDs if it's column |
| 177 | +For i = 0 To numberOfFrameElements - 1 |
| 178 | + 'Get frame type to check if it's a column |
| 179 | + etModel.FrameObj.GetDesignOrientation frameElements(i), frameType |
| 180 | +
|
| 181 | + 'Check if frame is vertical (column) |
| 182 | + If frameType = eFrameDesignOrientation.eFrameDesignOrientation_Column Then |
| 183 | + GetNextCell().Value = frameElements(i) |
| 184 | + End If |
| 185 | +Next i |
| 186 | +``` |
| 187 | + |
| 188 | +Get beam elements |
| 189 | +```visualbasic |
| 190 | +'Get All Frame Objects |
| 191 | +Dim numberOfFrameElements As Long, frameElements() As String |
| 192 | +Dim frameType As eFrameDesignOrientation |
| 193 | +
|
| 194 | +'Get all frame object names |
| 195 | +etModel.FrameObj.GetNameList numberOfFrameElements, frameElements |
| 196 | +
|
| 197 | +'Loop through all object and print their IDs if it's beam |
| 198 | +For i = 0 To numberOfFrameElements - 1 |
| 199 | + 'Get frame type to check if it's a column |
| 200 | + etModel.FrameObj.GetDesignOrientation frameElements(i), frameType |
| 201 | +
|
| 202 | + 'Check if frame is beam |
| 203 | + If frameType = eFrameDesignOrientation.eFrameDesignOrientation_Beam Then |
| 204 | + GetNextCell().Value = frameElements(i) |
| 205 | + End If |
| 206 | +Next i |
| 207 | +``` |
| 208 | +#### Shell Elements |
| 209 | +```visualbasic |
| 210 | +'Get all shell element names |
| 211 | +etModel.AreaObj.GetNameList numberOfSlabs, SlabNames |
| 212 | +
|
| 213 | +'Loop through all shell elements and write their names/IDs |
| 214 | +For i = 0 To numberOfSlabs - 1 |
| 215 | + GetNextCell().Value = SlabNames(i) |
| 216 | +Next i |
| 217 | +``` |
| 218 | +#### Selected objects |
| 219 | +```visualbasic |
| 220 | +'Get selected frame objects |
| 221 | +Dim numberOfSelectedObjects As Long |
| 222 | +Dim ObjectType() As Long, ObjectName() As String |
| 223 | +
|
| 224 | +' Get all selected objects |
| 225 | +etModel.SelectObj.GetSelected numberOfSelectedObjects, ObjectType, ObjectName |
| 226 | +
|
| 227 | +'Loop through all joint objects in the model |
| 228 | +GetNextCell().Value = "Joint Objects" |
| 229 | +For i = 0 To numberOfSelectedObjects - 1 |
| 230 | + If ObjectType(i) = 1 Then ' 1 = Joint object |
| 231 | + GetNextCell().Value = ObjectName(i) |
| 232 | + End If |
| 233 | +Next i |
| 234 | +
|
| 235 | +' Loop through all selected objects and filter for frame objects |
| 236 | +GetNextCell().Value = "Frame Objects" |
| 237 | +For i = 0 To numberOfSelectedObjects - 1 |
| 238 | + If ObjectType(i) = 2 Then ' 2 = Frame object |
| 239 | + GetNextCell().Value = ObjectName(i) |
| 240 | + End If |
| 241 | +Next i |
| 242 | +
|
| 243 | +' Loop through all selected objects and filter for slab objects |
| 244 | +GetNextCell().Value = "Slab Objects" |
| 245 | +For i = 0 To numberOfSelectedObjects - 1 |
| 246 | + If ObjectType(i) = 5 Then ' 5 = Slab object |
| 247 | + GetNextCell().Value = ObjectName(i) |
| 248 | + End If |
| 249 | +Next i |
| 250 | +``` |
| 251 | + |
| 252 | +#### Section Data |
| 253 | +```visualbasic |
| 254 | +'Extract Section Data |
| 255 | +Dim elementID As Long, sectionName As String, materialName As String |
| 256 | +
|
| 257 | +elementID = 1 |
| 258 | +GetNextCell().Value = elementID |
| 259 | +
|
| 260 | +'Get section name from elementID |
| 261 | +etModel.FrameObj.GetSection elementID, sectionName, "" |
| 262 | +GetNextCell().Value = sectionName |
| 263 | +
|
| 264 | +'Get material name from section |
| 265 | +etModel.PropFrame.GetMaterial sectionName, materialName |
| 266 | +GetNextCell().Value = materialName'Material |
| 267 | +
|
| 268 | +'Section Type and Size |
| 269 | +Dim sectionType As eFramePropType, sectionSize As String |
| 270 | +Dim t3 As Double, t2 As Double, Color As Long, Notes As String, GUID As String |
| 271 | +
|
| 272 | +'Get Section Type |
| 273 | +etModel.PropFrame.GetTypeOAPI sectionName, sectionType |
| 274 | +
|
| 275 | +'If rectangular section then width and depth |
| 276 | +If sectionType = eFramePropType.eFramePropType_Rectangular Then |
| 277 | + 'Get rectangle section size |
| 278 | + etModel.PropFrame.GetRectangle sectionName, "", materialName, t3, t2, Color, Notes, GUID |
| 279 | + GetNextCell().Value = t2'Width |
| 280 | + GetNextCell().Value = t3'Depth |
| 281 | +
|
| 282 | + 'Get rectangle frame length |
| 283 | + Dim elementLength As Double |
| 284 | + Dim iNode As String, jNode As String |
| 285 | + Dim x1 As Double, y1 As Double, z1 As Double |
| 286 | + Dim x2 As Double, y2 As Double, z2 As Double |
| 287 | +
|
| 288 | + 'Get element end nodes |
| 289 | + etModel.FrameObj.GetPoints elementID, iNode, jNode |
| 290 | +
|
| 291 | + 'Get coordinates of frame end points |
| 292 | + etModel.PointObj.GetCoordCartesian iNode, x1, y1, z1 |
| 293 | + etModel.PointObj.GetCoordCartesian jNode, x2, y2, z2 |
| 294 | +
|
| 295 | + 'Calculate length using distance formula |
| 296 | + elementLength = Sqr((x2 - x1) ^ 2 + (y2 - y1) ^ 2 + (z2 - z1) ^ 2) |
| 297 | + GetNextCell().Value = elementLength 'Element Length |
| 298 | +End If |
| 299 | +``` |
| 300 | + |
| 301 | +## Conclusion |
| 302 | +- Extracting data from ETABS is a perfect way to integrate your model with your design sheet. |
| 303 | +- Additionally, this approach works perfectly with code for extracting results. |
0 commit comments