주 콘텐츠로 건너뛰기
Example 생성 편집

예시: Excel VBA

shutterstock_1916341625-20231115-062550.jpg

VBA

VBA(Visual Basic for Applications)는 Microsoft에서 제공하는 프로그래밍 언어로, 주로 Microsoft Office 제품군(예: Excel, Word, PowerPoint, Access)에서 매크로를 작성하는 데 사용됩니다. VBA를 활용하면 반복 작업을 자동화하고, 각 애플리케이션에 사용자 정의 기능을 추가할 수 있습니다.

VBA의 주요 특징과 활용 목적은 다음과 같습니다.
 

  1. 프로그래밍 언어: VBA는 Visual Basic을 기반으로 하며, 프로그래밍 언어의 기본 기능을 지원합니다. 이를 통해 조건문, 반복문, 변수, 함수, 객체, 클래스, 모듈 등을 활용하여 코드를 작성할 수 있습니다.
  2. 자동화: VBA는 반복적인 작업을 자동화할 수 있습니다. 예를 들어, Excel에서 워크시트 데이터를 처리하거나 특정 조건에 따라 문서를 생성하는 작업 등에 활용됩니다.
  3. 사용자 정의 함수 및 매크로: 사용자는 VBA로 사용자 정의 함수와 매크로를 만들 수 있습니다. 이는 기존 애플리케이션의 기능을 확장하거나 특정 요구사항에 맞는 솔루션을 구현하는 데 유용합니다.
  4. 이벤트 처리: VBA는 애플리케이션에서 발생하는 이벤트(예: 버튼 클릭, 시트 변경)를 처리할 수 있어, 상호작용이 가능하고 반응형으로 동작하는 애플리케이션을 만들 수 있습니다.
  5. 매크로 기록: 일상적인 작업을 기록하여 VBA 코드를 자동으로 생성할 수 있으며, 생성된 코드를 편집하는 것도 가능합니다. 이를 통해 빠르게 코드를 작성할 수 있습니다.
  6. Access 데이터베이스 프로그래밍: VBA는 Microsoft Access와 같은 애플리케이션에서 데이터베이스와 연동하는 기능을 제공합니다.


VBA를 사용하려면 각 Microsoft Office 애플리케이션에 내장된 VBA 편집기를 이용해 코드를 작성하고 실행합니다. VBA는 업무 프로세스 자동화, 보고서 생성, 데이터 처리, 사용자 정의 폼 및 함수 구현 등 다양한 작업에 활용됩니다. 강력한 도구이지만, VBA로 작업할 때는 코드 작성과 디버깅에 익숙해질 필요가 있습니다.

 

Welcome to VBA

MS Office 제품에서 VBA에 접근하려면 ALT+F11을 누르거나, "Developer" 탭으로 이동합니다. VBA에서 REST API 요청을 보내기 위해 별도의 설치 과정은 필요하지 않습니다.

 

VBA에서 JSON 다루기

VBA(Visual Basic for Applications)에서 JSON 데이터를 처리하려면 일반적으로 외부 라이브러리의 도움이 필요합니다. VBA 자체에는 JSON을 처리하기 위한 기본 함수나 라이브러리가 포함되어 있지 않습니다. 따라서 JSON 처리를 위해 'VBA-JSON'과 같은 라이브러리를 활용할 수 있습니다. 아래에서는 VBA에서 JSON 데이터를 처리하는 방법을 안내합니다.

 

  1. VBA-JSON 라이브러리 설치: VBA-JSON 라이브러리는 JSON 데이터를 파싱하고 생성하는 기능을 제공합니다. 먼저 해당 라이브러리를 다운로드하여 설치해야 합니다. VBA-JSON은 GitHub에서 제공되며, JsonConverter.bas 파일을 다운로드한 후 VBA 프로젝트에 추가할 수 있습니다.  GitHub - VBA-tools/VBA-JSON: JSON conversion and parsing for VBA
  2. VBA 프로젝트에 라이브러리 추가: VBA-JSON의 JsonConverter.bas 파일을 VBA 프로젝트에 추가하려면 다음 단계를 따르세요.
    1. VBA 프로젝트를 열고 'Module' 탭을 선택합니다.
    2. "File" 메뉴를 선택한 뒤 "Import File"을 클릭합니다.
    3. 가져올 파일로 JsonConverter.bas 파일을 선택하여 불러옵니다.
  3. VBA 참조(Reference) 추가: JsonConverter.bas 파일을 사용하기 위해서는 VBA의 Dictionary 자료형을 Early binding 방식으로 사용해야 합니다. 이를 위해 "Microsoft Scripting Runtime" 참조를 추가해야 합니다.

    다음 단계를 진행합니다.

    1. Tools 메뉴에서 References를 실행합니다.
    2. "Microsoft Scripting Runtime"을 찾아 체크한 후, "OK"를 클릭합니다.

image-20231020-012805.png
VBA - JSON

 

  • JSON 데이터 파싱

설치한 라이브러리의 ParseJson 함수를 사용하여 VBA에서 JSON 데이터를 파싱할 수 있습니다. 아래는 JSON 데이터를 파싱하는 예제입니다.

Option Explicit

Sub jsonParsing()

    'JSON 문자열을 파싱하여 VBA 데이터로 변환
    Dim jsonData As String
    Dim data As Scripting.Dictionary
    
    jsonData = "{""name"": ""John"", ""age"": 30, ""city"": ""New York""}"
    Set data = JsonConverter.ParseJson(jsonData)
    
    '결과 출력
    Debug.Print data("name")  'John
    
End Sub 

 

  • JSON 데이터 생성

VBA 데이터를 JSON으로 변환하려면 ConvertToJson 함수를 사용할 수 있습니다. 아래는 VBA Dictionary를 JSON 문자열로 변환하는 예제입니다.

Option Explicit

Sub jsonParsing()

    'VBA Dictionary를 JSON 문자열로 변환
    Dim jsonData As String
    Dim data As Scripting.Dictionary
    Set data = New Dictionary
    
    data.Add "name", "John"
    data.Add "age", 30
    data.Add "city", "New York"
    
    jsonData = JsonConverter.ConvertToJson(data)
    
    '결과 출력
    Debug.Print (jsonData) '{"name":"John","age":30,"city":"New York"}
    
End Sub 

 

실습 예제

VBA를 사용하여 직사각형 단면을 갖는 단순보를 생성하는 예제를 진행해 보겠습니다.

VBA의 특성을 고려하여, 본 예제에서는 Excel 시트를 활용합니다.

 

  • 먼저, 시트에 변수를 입력할 수 있는 입력 창을 구성합니다.

image-20231020-082034.png

 

  • REST API 요청을 함수로 생성합니다.
Option Explicit

Function WebRequest(Method As String, Command As String, Body As String) As String

    Dim TCRequestItem As Object
    Dim baseURL As String
    Dim URL As String
    Dim MAPI_Key As Variant
    
    Set TCRequestItem = CreateObject("WinHttp.WinHttpRequest.5.1")
    
    'SetTimeouts(resolveTimeout, ConnectTimeout, SendTimeout, ReceiveTimeout)
    TCRequestItem.SetTimeouts 200000, 200000, 200000, 200000
    
    baseURL = Cells(2, 7).Value
    MAPI_Key = Cells(3, 7).Value
    
    URL = baseURL & Command
    TCRequestItem.Open Method, URL, False
    TCRequestItem.SetRequestHeader "Content-type", "application/json"
    TCRequestItem.SetRequestHeader "MAPI-Key", MAPI_Key
    TCRequestItem.Send Body
    WebRequest = TCRequestItem.ResponseText
    
    Debug.Print Command & " : " & TCRequestItem.Status & " - " & TCRequestItem.StatusText

End Function 

 

  • SimpleBeam을 생성하는 Sub 모듈을 작성합니다.
Sub CreateSimpleBeam()
    
    Dim i, j, k As Integer
    
    'input data from sheets
    Dim dist As String
    Dim force As String
    Dim length As Double
    Dim height As Double
    Dim width As Double
    Dim direction As String
    Dim loadValue As Double
    Dim modelID As Range
    Dim loadCase As Range
    Dim matSt As String
    Dim matDB As String
    
    dist = UCase(Cells(5, "E").Value)
    force = UCase(Cells(6, "E").Value)
    
    length = Cells(8, "E").Value
    height = Cells(9, "E").Value
    width = Cells(10, "E").Value
    
    direction = Cells(9, "I").Value
    loadValue = Cells(9, "J").Value
    
    matSt = Cells(5, "J").Value
    matDB = Cells(6, "J").Value
    
    Set loadCase = Range(Cells(12, "I"), Cells(13, "J"))
    Set modelID = Range(Cells(12, "E"), Cells(15, "E"))
    
    'Dictionary
    Dim dicMain As Scripting.Dictionary
    Dim dicSub1 As Scripting.Dictionary
    Dim dicSub2 As Scripting.Dictionary
    Dim dicSub3 As Scripting.Dictionary
    Dim dicSub4 As Scripting.Dictionary
    Dim response As String
    Dim body As String
    
    'Create New File
    response = WebRequest("POST", "/doc/new", "{}")
    Debug.Print response
    
    'Create Unit Body and Request API
    Set dicMain = New Dictionary
    Set dicSub1 = New Dictionary: Set dicSub2 = New Dictionary
    
    dicSub2.Add "DIST", dist
    dicSub2.Add "FORCE", force
    
    dicSub1.Add "1", dicSub2
    
    dicMain.Add "Assign", dicSub1
    
    body = JsonConverter.ConvertToJson(dicMain)
    response = WebRequest("PUT", "/db/unit", body)
    Debug.Print response
    
    Set dicMain = Nothing
    Set dicSub1 = Nothing: Set dicSub2 = Nothing
    
    'Create Material Body and Request API
    Set dicMain = New Dictionary: Set dicSub1 = New Dictionary
    Set dicSub2 = New Dictionary: Set dicSub3 = New Dictionary
    
    dicSub3.Add "P_TYPE", 1
    dicSub3.Add "STANDARD", matSt
    dicSub3.Add "DB", matDB
    
    dicSub2.Add "TYPE", "CONC"
    dicSub2.Add "NAME", matDB
    dicSub2.Add "PARAM", Array(dicSub3)
    
    dicSub1.Add modelID(1, 1), dicSub2
    
    dicMain.Add "Assign", dicSub1
    
    body = JsonConverter.ConvertToJson(dicMain)
    response = WebRequest("POST", "/db/matl", body)
    Debug.Print response
    
    Set dicMain = Nothing: Set dicSub1 = Nothing
    Set dicSub2 = Nothing: Set dicSub3 = Nothing
    
    'Create Section Body and Request API
    Set dicMain = New Dictionary: Set dicSub1 = New Dictionary
    Set dicSub2 = New Dictionary: Set dicSub3 = New Dictionary: Set dicSub4 = New Dictionary
    
    dicSub4.Add "vSIZE", Array(height, width)
    
    dicSub3.Add "USE_SHEAR_DEFORM", True
    dicSub3.Add "SHAPE", "SB"
    dicSub3.Add "DATATYPE", 2
    dicSub3.Add "SECT_I", dicSub4
    
    dicSub2.Add "SECTTYPE", "DBUSER"
    dicSub2.Add "SECT_NAME", "Rectangular"
    dicSub2.Add "SECT_BEFORE", dicSub3
    
    dicSub1.Add modelID(2, 1), dicSub2
    
    dicMain.Add "Assign", dicSub1
    
    body = JsonConverter.ConvertToJson(dicMain)
    response = WebRequest("POST", "/db/sect", body)
    Debug.Print response
    
    Set dicMain = Nothing: Set dicSub1 = Nothing
    Set dicSub2 = Nothing: Set dicSub3 = Nothing: Set dicSub4 = Nothing
    
    'Create Node Body and Request API
    Set dicMain = New Dictionary: Set dicSub1 = New Dictionary
    
    Dim num_division As Long
    Dim interval As Double
    
    num_division = 20
    interval = length / num_division
    
    For i = 0 To num_division
        Set dicSub2 = New Dictionary
        
        dicSub2.Add "X", i * interval
        dicSub2.Add "Y", 0
        dicSub2.Add "Z", 0
        
        dicSub1.Add modelID(3, 1) + i, dicSub2
        
        Set dicSub2 = Nothing
    Next i
    
    dicMain.Add "Assign", dicSub1
    
    body = JsonConverter.ConvertToJson(dicMain)
    response = WebRequest("POST", "/db/node", body)
    Debug.Print response
    
    Set dicMain = Nothing: Set dicSub1 = Nothing
   
    'Create Element Body and Request API
    Set dicMain = New Dictionary: Set dicSub1 = New Dictionary
        
    For i = 0 To num_division
        Set dicSub2 = New Dictionary
        
        dicSub2.Add "TYPE", "BEAM"
        dicSub2.Add "MATL", modelID(1, 1)
        dicSub2.Add "SECT", modelID(2, 1)
        dicSub2.Add "NODE", Array(modelID(3, 1) + i, modelID(3, 1) + i + 1)
        
        dicSub1.Add modelID(4, 1) + i, dicSub2
        
        Set dicSub2 = Nothing
    Next i
    
    dicMain.Add "Assign", dicSub1
    
    body = JsonConverter.ConvertToJson(dicMain)
    response = WebRequest("POST", "/db/elem", body)
    Debug.Print response
    
    Set dicMain = Nothing: Set dicSub1 = Nothing
    
    'Create Boundary Body and Request API
    Set dicMain = New Dictionary: Set dicSub1 = New Dictionary
    Set dicSub2 = New Dictionary: Set dicSub3 = New Dictionary
    
    dicSub3.Add "ID", 1
    dicSub3.Add "CONSTRAINT", "1111000"
    
    dicSub2.Add "ITEMS", Array(dicSub3)
    
    dicSub1.Add modelID(3, 1), dicSub2
    
    Set dicSub2 = Nothing: Set dicSub3 = Nothing
    Set dicSub2 = New Dictionary: Set dicSub3 = New Dictionary
    
    dicSub3.Add "ID", 1
    dicSub3.Add "CONSTRAINT", "0111000"
    
    dicSub2.Add "ITEMS", Array(dicSub3)
    
    dicSub1.Add modelID(3, 1) + num_division, dicSub2
    
    dicMain.Add "Assign", dicSub1
    
    body = JsonConverter.ConvertToJson(dicMain)
    response = WebRequest("POST", "/db/cons", body)
    Debug.Print response
    
    Set dicMain = Nothing: Set dicSub1 = Nothing
    Set dicSub2 = Nothing: Set dicSub3 = Nothing
    
    'Create Load Cases and Request API
    Set dicMain = New Dictionary: Set dicSub1 = New Dictionary
    
    For i = 0 To loadCase.Rows.Count - 1
        Set dicSub2 = New Dictionary
        
        dicSub2.Add "NAME", loadCase(i + 1, 2)
        dicSub2.Add "TYPE", "USER"
        
        dicSub1.Add i + 1, dicSub2
        
        Set dicSub2 = Nothing
    Next i
    
    dicMain.Add "Assign", dicSub1
    
    body = JsonConverter.ConvertToJson(dicMain)
    response = WebRequest("POST", "/db/stld", body)
    Debug.Print response
    
    Set dicMain = Nothing: Set dicSub1 = Nothing
    
    'Create Self-Weight Load Body and Request API
    Set dicMain = New Dictionary: Set dicSub1 = New Dictionary
    Set dicSub2 = New Dictionary
    
    dicSub2.Add "LCNAME", loadCase(1, 2)
    dicSub2.Add "FV", Array(0, 0, -1)
    
    dicSub1.Add "1", dicSub2
    
    dicMain.Add "Assign", dicSub1
    
    body = JsonConverter.ConvertToJson(dicMain)
    response = WebRequest("POST", "/db/bodf", body)
    Debug.Print response
    
    Set dicMain = Nothing: Set dicSub1 = Nothing
    Set dicSub2 = Nothing
    
    'Create Beam Load Body and Request API
    Set dicMain = New Dictionary: Set dicSub1 = New Dictionary
    
    For i = 0 To num_division - 1
        Set dicSub2 = New Dictionary: Set dicSub3 = New Dictionary
        
        dicSub3.Add "ID", 1
        dicSub3.Add "LCNAME", loadCase(2, 2)
        dicSub3.Add "CMD", "BEAM"
        dicSub3.Add "TYPE", "UNILOAD"
        dicSub3.Add "DIRECTION", direction
        dicSub3.Add "D", Array(0, 1)
        dicSub3.Add "P", Array(loadValue, loadValue)
        
        dicSub2.Add "ITEMS", Array(dicSub3)
        
        dicSub1.Add modelID(4, 1) + i, dicSub2
        
        Set dicSub2 = Nothing: Set dicSub3 = Nothing
    Next i
    
    dicMain.Add "Assign", dicSub1
    
    body = JsonConverter.ConvertToJson(dicMain)
    response = WebRequest("POST", "/db/bmld", body)
    Debug.Print response
    
    Set dicMain = Nothing: Set dicSub1 = Nothing
    
    'Create Load Combinations Body and Request API
    Set dicMain = New Dictionary: Set dicSub1 = New Dictionary
    Set dicSub2 = New Dictionary

    Dim vCOMB() As Object
    ReDim vCOMB(loadCase.Rows.Count - 1)
    
    For i = 0 To loadCase.Rows.Count - 1
        Set dicSub3 = New Dictionary
        
        dicSub3.Add "ANAL", "ST"
        dicSub3.Add "LCNAME", loadCase(i + 1, 2)
        dicSub3.Add "FACTOR", loadCase(i + 1, 1)
        
        Set vCOMB(i) = dicSub3
        
        Set dicSub3 = Nothing
    Next i
    
    dicSub2.Add "NAME", "Comb1"
    dicSub2.Add "ACTIVE", "ACTIVE"
    dicSub2.Add "iTYPE", 0
    dicSub2.Add "vCOMB", vCOMB
    
    dicSub1.Add "1", dicSub2
    
    dicMain.Add "Assign", dicSub1
    
    body = JsonConverter.ConvertToJson(dicMain)
    response = WebRequest("POST", "/db/lcom-gen", body)
    Debug.Print response
   
    Set dicMain = Nothing: Set dicSub1 = Nothing
    Set dicSub2 = Nothing
    
End Sub 

 

  • 앞서 작성한 Sub 모듈을 실행할 수 있도록 버튼을 생성합니다. Developer 탭에서 버튼을 선택합니다. (Developer 도구는 Excel Options의 Customize Ribbon 설정에서 활성화할 수 있습니다.)

image-20231020-093739.png

 

  • 적절한 위치에 버튼을 생성한 후, 아래와 같이 실행 가능한 매크로 모듈 목록을 확인할 수 있습니다. 미리 삽입해 둔 Sub 모듈을 선택하여 적용합니다.

image-20231020-094040.png

 

  • MIDAS CIVIL NX를 실행하고 API 서버에 연결한 뒤, API Settings에서 base URL/MAPI-Key를 입력하고 버튼을 실행합니다.

image-20231020-094223.png

위 과정을 완료한 첨부 파일을 참고하시기 바랍니다.

 

이제 의도한 구조가 MIDAS CIVIL NX에 생성되었습니다.

image-20231020-094316.png

 

추가 예제

Excel VBA를 이용한 PSC Beam Girder

본 PSC Beam Girder는 한국 도로교 설계기준(Highway Bridge Design Standard)을 기반으로 한 Steel Crossbeam 예제이며, Excel VBA를 사용합니다.

 

구조 엔지니어를 위한 최고의 도구


VBA는 Excel로 작성된 구조 계산 시트와 결합될 때 가장 큰 강점을 발휘할 수 있습니다.

특히 해석 결과를 계산 시트에 반복적으로 입력해야 하는 경우, API는 매우 좋은 선택이 될 수 있습니다.

VBA와 함께 MIDAS Open API의 첫걸음을 시작해 보시기 바랍니다.

0
컨텐츠가 도움이 되셨나요?