VBA 강의(1) - Flash Tank 계산 (1)

1. Flash Tank 엔지니어링

   1.1 Flash 증기 및 드레인 유량 계산

   1.2 Flash Tank의 운전 압력

   1.3 Flash Tank 설계

   1.4 Drain 계통 설계

2. 엑셀 시트 디자인

3. VBA 코딩

   3.1 [일반]-[선언] 부

   3.2 Private Sub Worksheet_Activate() 이벤트

   3.3 Private Sub Worksheet_Change(ByVal Target As Excel.Range)

맺음 말


* 파일 다운로드 : Flash Tank Excel (엑셀 파일 열기시 "열기(매크로 포함)"으로 열어야 VBA 코드를 실행할 수 있습니다.)

 

고압의 응축수가 압력 강하에 따른 강제 증발(Flash) 현상에 의해 저압의 포화 수증기와 포화수로 분리시키는 용기가 Flash Tank입니다.

보일러 블로운 다운 탱크(Blow-down Tank), 터빈 구역에 설치되어 각종 터빈 주변 증기 계통의 배수(Drain)을 받아 들이는 Condensate Drain Tank가 일종의 Flash Tank입니다.

이러한 Flash Tank에서 열정산에 의해 강제 증발 현상의 계산하는 것이 Flash Tank 게산입니다.  전혀 어려운 계산이 아닌데, 막상 계산하려면 증기표를 찾아야 하는 번거러움이 따릅니다.

이러한 Flash Tank 계산을 ESCommon.dll의 증기표 기능을 사용해 엑셀의 VBA로 코딩을 해 놓으면, 필요할 때마다 엑셀을 열어 손쉽게 사용할 수 있습니다.

차례

1. Flash Tank 엔지니어링

1.1 Flash 증기 및 드레인 유량 계산

Flash Tank로 유입되는 고압 포화수의 압력과 유량, 그리고 Flash Tank 내부 압력을 알 때 Flash Tank에서 Flash에 의해 발생되는 증기 유량은 다음과 같이 계산됩니다.

Wfs = Wc * (Hc - Hd) / (Hfs - Hd)

(주)

Wfs

: Flash Tank에서 발생하는 Flash 증기 유량

 

Wc

: Flash Tank로 유입되는 고압 포화수의 유량, Wfs와 같은 단위

 

Hc

: Flash Tank로 유입되는 고압 포화수의 엔탈피

 

Hd

: Flash Tank에서 배출되는 드레인 엔탈피(Flash Tank 운전 압력에서의 포화수 엔탈피), Hc와 같은 단위

 

Hfs

: Flash Tank에서 발생하는 Flash 증기 엔탈피(Flash Tank 운전 압력에서의 포화 증기 엔탈피), Hc와 같은 단위

그리고, Flash Tank에서 배출되는 드레인 유량은, Wc - Wfs로 계산됩니다.   아주 쉽죠.

Flash Tank로 유입되는 고압 응축수(혹은 포화수)는 저압의 Flash Tank 내에서 고압 상태 그대로 존재할 수 없으며, Flash Tank 압력에 해당하는 포화수로 바뀌게 됩니다.   이렇게, Flash Tank로 유입되는 고압 응축수가 저압 포화수로 바뀌면서 남는 에너지(Hc - Hd)가 Flash을 유발시키며, Flash Tank 내부에서 증발을 위해 필요한 에너지는 Flash Tank 압력에서의 포화 증기와 포화 수의 엔탈피 차이(Hfs - Hd)입니다.  이러한 이유로 Flash Tank에서 뱔생하는 Flash Tank 증기 유량을 위와 같이 게산합니다.

1.2 Flash Tank의 운전 압력

Flash Tank로 유입되는 응축수의 압력에 관계없이, Flash Tank의 압력은 Flash Tank의 Vent Pipe가 연결된 계통의 압력보다, Vent Pipe에서의 압력 강하량 만큼 높습니다.

예를 들어, 대기 중으로 배출되는 Boiler Blow-down Tank의 압력은 대기압 보다 약간 높습니다.  Vent Pipe에서의 증기 유속은 일반 포화 증기의 배관 선정 유속과 동일하게 하면 되는데(20 m/sec 이하 정도), Vent Pipe의 길이가 100 meter를 넘지 않는다면 Vent Pipe에서의 압력 강하는 0.1 kg/cm2 이하입니다.  그러므로, 대기 중으로 Flash Steam을 배출하는 Boiler Blow-down Tank의 압력은 대개 0.1 kg/cm2g 이며, Tank에 설치되어 있는 온도계의 온도가 대략 101 oC 정도 가리키는 것을 볼 수 있습니다.   

보일러 드럼에서 배출되는 고온수의 높은 압력은 Boiler 'Blow-down Tank로 들어오기 전에 Blow-down Valve에서 대부분의 압력이 떨어지며, Blow-down Valve 후단 배관 내부에서는 포화수와 포화 증기가 혼재해서 흐르는 2 Phase Flow가 되어, 속도도 빠르고 소음과 진동, 침식등이 일어납니다.  그러므로, 가능하면 Blow-down Valve를 Blow-down Tank 가까이 설치해서 2 Phase Flow 구간을 짧게하고, 침식 등을 고려해 배관 두께을 보다 두껍게 하는 것이 좋습니다.

Flash Tank의 Vent Pipe가 탈기기(Deaerator)에 연결되어 있으면, Flash Tank의 압력은 탈기기 압력보다 0.1내지 0.2 kg/cm2 정도 높으며, 복수기(Condenser)에 연결되어 있으면 복수기 압력보다 약간 높습니다.

1.3 Flash Tank 설계

Flash Tank의 직경은, Flash Tank 내에서의 증기의 유속이 1 m/sec 이하가 되도록 선정하며, Flash Tank의 높이는 직경의 1.5 배 정도로 설계합니다.  Flash Tank의 직경은, 물방울(포화수)이 증기와 함께 Vent Pipe을 통해 배출되는 양과 관계 있습니다.  직경이 작으면, Vent Pipe를 통해 물방울이 많이 딸려나가며, 직경이 크면 딸려 나가는 물방울 양이 작습니다.   대기 중으로 배출하는 Boiler Blow-down Tank의 Vent Pipe 밑에 서 있으면 비가 오는데, 바로 이 현상에 의해 비가 오는 것입니다.   비가 적게 오게 하기 위해서 Boiler Blow-down Tank의 직경을 무작정 크게할 수도 없겠지요.  비가 오는 것을 참던가 아니면, Vent Pipe에 Silencer를 설치해서 소음도 줄이고 비가 오는 것을 방지하기도 합니다.  Blow-down Tank의 Vent Pipe에서 내리는 비는 약품이 석여 있는 비이므로, 그 밑에 오래 서있지는 마시기 바랍니다.

Flash Tank로 유입되는 고압의 고온수는 2 Phase 상태로 유입되므로 침식력(Erosion Force)이 매우 강합니다.  이러한 침식력에 견디도록 하기 위해서, Flash Tank로 유입되는 고압의 고온수는 법면 유로(Tangential Flow)로 유입되도록 설계하며, 고압 고온수가 유입되는 부위는 보강 철판을 덧대서 침식에 오래 견디도록 설계합니다.

Vent Pipe에 밸브가 설치되어 있지 않다면, Flash Tank의 설계 압력은 Vent Pipe가 연결된 계통의 설계 압력과 동일하게 선정하고, 안전변(Safety Valve)을 설치하지 않습니다.  예를 들어 복수기에 연결되어 있다면 복수기의 설계 압력과 동일하게, 탈기기에 연결되어 있다면 탈기기의 설계 압력과 동일하게 선정합니다.   대기 중으로 배출되는 경우에는, 최저 설계 압력인 3.5 kg/cm2g(50 psig)로 선정합니다.

Vent Pipe에 밸브가 설치되어 있다면, Flash Tank의 설계 압력은 고압 고온수의 계통의 설계 압력과 동일하게 선정하고 안전변을 설치하지 않거나, Vent Pipe가 연결된 계통의 설계 압력과 동일하게 선정하고 안전변을 설치합니다.  이때 안전변의 설정 압력(Set Pressure)는 선정된 설계 압력으로 하고, 정격 용량은 최대 Flash Steam 양에 10% 정도의 여유를 더해 선정합니다.

Flash Tank의 설계 압력은 설계 압력에서의 포화 온도로 선정합니다.

1.4 Drain 계통 설계

Flash Tank의 Drain 계통은 급수가열기 배수 배관 선정(Cascade Heater Drain Line Sizing)과 동일하게 하면 됩니다.   저희 ES_CasDrain 프로그램을 사용하여 LCV 전후단의 조건을 구한 다음, Drain Line에 LCV가 설치되어 있는 경우에는 LCV 설계 조건으로, Steam Trap이나 Resistance Orifice가 설치되어 있는 경우에는 Steam Trap이나 Resistance Orifice의 설계 조건으로 Data Sheet에 기술해 주면 됩니다.   

Resistance Orifice가 설치되어 있는 경우에 종종 엔지니어가 Orifice 구경을 선정해 주어야 하는 경우가 있습니다.  이러한 경우에는, ES_CasDrain으로 계산된 LCV 후단 압력을 구해, ES_StmNzl 프로그램의 출구측(지점 3) 압력으로 입력하고, 입구측(지점 1) 조건은 Flash Tank의 Drain 조건을 입력해 ES_StmNzl을 돌려서 얻은 단위 면적당 질량 유량을 이용해 Resistance Orifice의 구경을 선정하면 됩니다.   ES_StmNzl은 노즐(Nozzle)의 해석 프로그램이므로, Orifice를 정확히 해석할 수는 없지만, 별도의 Orifice 해석 프로그램이 없는 경우에는, 사용해도 큰 무리는 없습니다.  

가능하면, Orifice 제작자에게 문의하는 것이 좋으며, 이때 주의할 점은 원하는 Resistance Orifice의 압력 강하(dP) 값이 Flange Tap dP 값이 아니고 Permanent dP라는 것을 제작자에게 주지시켜야 합니다.   제작자가 유량 측정 용으로 사용하는 Orifice의 dP 값은 Flange Tap dP 값이므로, Resistance Orifice를 주문할 때 아무 언급 없이 Orifice dP 값을 주면, 제작자가 Flange Tap dP로 오해하는 경우가 종종 있습니다.

 

2. 엑셀 시트 디자인

Flash Tank 열정산 계산을 위한 엑셀 시트를 다음과 같이 디자인하였습니다.

 

그림 그리기 도구를 사용하여 그림을 그렸으며, 노란색 셀은 사용자 입력 창입니다.   사용자가 노란색 셀의 값을 입력하면, 자동으로 나머지 계산이 되도록 VBA 코딩을 할 것입니다.

 

3. VBA 코딩

이제 VBA 코딩을 해보도록 하겠습니다.   우선 "VBA 시작하기"에서의 설명에 따라, Visual Basic 편집기가 열려 있고, ESCommon.dll을 참조합니다.

"프로젝트 탐색기" 창에서 "Sheet1(Sheet1)"를 Double Click해서 Sheet1의 속성 창과 코딩 창을 엽니다.  그리고, 속성 창의 아래에서 네 번째 칸의 "Name" 칸에 "Flash Tk"라고 입력합니다.   그러면, "프로젝트 탐색기" 창에서 "Sheet1(Sheet1)"이 "Sheet1(Flash Tk)"로 바뀝니다.  그리고, 엑셀 창으로 가 보면, Sheet1의 이름이 "Flash Tk"로 바뀌어 있는 것을 볼 수 있습니다.   

괄호 밖의 "Sheet1"과 괄호 안의 "Flash Tk"는 모두 동일한 워크 시트를 대표하는 이름이며, 단지 사용 방법이 다를 뿐입니다.   괄호 밖의 "Sheet1" 명칭도, 속성 창에서 "이름" 칸의 이름을 변경하면 변경 가능합니다.   여기서는 일단 Sheet1 그대로 사용하기로 합니다.

아래의 코딩 내용을 읽을 때, 첨부된 엑셀 파일의 코딩 내용을 함꼐 보시기 바랍니다.

아울러, 엑셀 VBA 언어에 대한 이해도를 높이기 위해서는 처음 대하는 언어가 나오는 경우에 도움말에서 해당 언어의 용법에 대한 내용을 읽어 보는 것이 좋습니다.  엑셀 VBA 언어의 도움말은 VBE 창에서의 도움말을 보셔야 합니다.  엑셀 창의 도움말을 보시면 안됩니다.

3.1 [일반]-[선언] 부

[일반]-[선언] 부에서는 변수를 선언합니다.

1) Option Explicit 선언

코딩 창의 [일반]-[선언] 부에 "Option Explicit"라고 적어 넣습니다.

이는 선언되지 않은 변수는 사용할 없다는 의미이며, 선언되지 않은 변수를 사용하면 오류를 일으킵니다.

선언부에 "Option Explicit"를 적지 않으면, 변수를 선언하지 않고 코드 가운데에서 아무 변수나 사용하여도 오류를 일으키지 않으며, VBA는 해당 변수를 Variant로 선언된 것으로 간주하여 처리합니다.

얼 듯보면 "Option Explicit"를 적지 않는 것이 바람직할 것 처럼 보이지만, "Option Explicit"를 적지 않으면 프로그래머의 프로그램 코딩 실수를 쉽게 발견할 수 없습니다.  잘못 코딩하여도 오류로 처리하지 않으니까요.  예를 들어, SteamTP 라는 변수를 선언 없이 코딩에서 사용하고 있는 중에, 오타로 인해 StaemTP 라고 변수를 타이핑했을 때, 이를 실수로 보지 않고 또 다른 하나의 변수로 자동 처리함으로써, 프로그램 코딩의 실수를 쉽게 발견할 수가 없게 됩니다.  그러므로 "Option Explicit"를 코딩 전에 항상 선언할 것을 권합니다.

2) Dim xlsStable As ESCommon.Stable 선언

코딩 창의 [일반]-[선언] 부에 모듈 수준의 변수 "xlsStable"을 ESCommon.Stable 데이터 형식으로 선언합니다.

선언부에서 dim xlsStable as 라고 타이핑한 후 한 칸을 띄면, 현재 사용할 수 있는 데이터 형식과 dll 및 ocx 등이 모두 자동으로 나열됩니다.  그 가운데 ESCommon을 선택한 다음에, "."(점)을 타이핑하면 또 다시 ESCommon에서 사용할 수 있는 클래스(Class) 모듈이 자동으로 나열됩니다.  ESCommon에서 사용할 수 있는 클래스 모듈에는 Stable, Unit, dPCalc, Pipe 등의 4가지가 있습니다.  그 가운데 Stable을 선택하십시요.   Stable 클래스 모듈은 증기 테이블을 사용하기 위한 메소드와 속성들이 들어 있습니다.

그러면, xlsStable이라는 변수를 이용하여, ESCommon.dll의 Stable 클래스 모듈의 메소드와 속성들을 사용할 수 있습니다.   xlsStable을 원하는 다른 이름으로 바꾸어도 됩니다.

3) Dim xlsUnit As ESCommon.Unit 선언

같은 방법으로 xlsUnit를 ESCommon.dll의 Unit 클래스 모듈로 선언합니다.  Unit 클래스 모듈에는 단위를 저장하는 속성과 단위 변환을 할 수 있는 메소드가 들어 있습니다.

 

3.2 Private Sub Worksheet_Activate() 이벤트

Worksheet_Activate 이벤트는 해당 Worksheet가 활성화될 때 수행됩니다.  즉, 해당 Worksheet가 활성화될 때, 본 이벤트 안에 적혀있는 코드가 실행됩니다.   Worksheet가 활성화된다는 것은, 엑셀 창에서 해당 Worksheet를 클릭해 사용자에게 보여진다는 것입니다.

이 곳에서는 Worksheet가 활성화될 때, 셀에 단위를 입력하는 코딩을 할 것입니다.

1)

Set xlsStable = New ESCommon.Stable

 

Set xlsUnit = New ESCommon.Unit

일반 데이터 형식의 변수는 선언을 하면 바로 사용할 수 있지만, 개체(dll 및 ocx 포함)로 선언된 변수들은 위와 같이 Set New 문으로 다시 설정해 주어야 사용할 수 있습니다.

위와 같이 코딩하여, xlsStable과 xlsUnit를 Activate 이벤트 내에서 사용할 수 있도록 합니다.

2)

xlsStable.uPR = chyunit_kgpercm2a

 

xlsStable.uTP = chyunit_degC

 

xlsStable.uSVOL = chyunit_m3perkg

 

xlsStable.uENTH = chyunit_kcalperkg

xlsStable의 단위를 사용자가 원하는 단위로 설정합니다.   xlsStable이라고 타이핑하고, "."을 타이핑하면 사용할 수 있는 xlsStable의 속성과 메소드가 자동으로 나열됩니다.  

그 가운데 "u"로 시작하는 속성이 단위를 설정하는 속성입니다.   위의 코드에서는 앞으로의 Flash Tank 계산에서 필요한, 압력(uPR)과 온도(uTP), 비체적(uSVOL), 엔탈피(uENTH)의 단위를 설정하였습니다.   원하는 단위 속성을 선택한 다음, "="를 타이핑하면, 해당 단위 속성에서 사용할 수 있는 단위들이 자동으로 나열됩니다.  위의 예에서는, 압력 단위로 kg/cm2a 과, 온도 단위로는 oC, 비체적 단위로는 m3/kg, 엔탈피 단위로는 kcal/kg을 선택했습니다.

VBA 코딩 시에 개체나 클래스 모듈 다음에 "."을 타이핑하면 해당 개체나 클래스 모듈에서 사용할 수 있는 속성과 메소드가 자동으로 나열되고, 속성이나 메소드 가운데 하나를 선택한 다음 "="를 타이핑하면, 해당 속성이나 메소드에서 선택할 수 있는 내용들이 자동으로 나열되는 경우가 대부분입니다.    코딩 시에 이러한 기능을 자주 이용하시기 바랍니다.

3)

xlsUnit.uMFlow = chyunit_kgperhr

 

xlsUnit.uLen = chyunit_mm

 

xlsUnit.uVel = chyunit_mpersec

 

xlsUnit.uSVOL = chyunit_m3perkg

xlsStable과 동일한 방법으로 xlsUnit의 단위를 설정합니다.  질량 유량(uMFlow)와 길이(uLen), 속도(uVel), 비체적(uSVOL)의 단위를 각각 kg/hr, mm, m/sec, m3/kg으로 설정했습니다.

4)

Range("c27") = xlsStable.sPR

 

Range("c28") = xlsStable.sTP

 

Range("c29") = xlsStable.sENTH

Flash Tank의 열정산과 관련된 변수의 단위는 증기 테이블의 단위인 xlsStable의 단위를 입력합니다.  Range("c27")은 셀 C27을 나타냅니다.  그리고 그 셀에 xlsStable의 압력 단위 문자열 속성인 xlsStable.sPR 을 입력합니다.  xlsStable 속성 가운데 "s"로 시작하는 속성이 단위 문자열 속성입니다.  

원래 Range 개체의 값을 정확히 나타내는 방법은 Value 속성을 사용해야 합니다.  즉 Range("c27").Value = 이라고 표시해야 합니다.  하지만, Range 개체의 기본(Default) 속성이 Value 속성이므로, Range 개체의 속성을 생략하면 이는 Value 속성을 나타냅니다.

5)

Range("c30") = xlsUnit.sMFlow

 

Range("g23") = xlsUnit.sVel

 

Range("g25") = xlsUnit.sLen

 

Range("g26") = xlsUnit.sLen

Flash Tank의 크기 계산과 관련된 변수의 단위는 단위 환산의 단위인 xlsUnit의 단위를 입력합니다.  

셀의 열(Column)을 나타내는 알파벳은 대문자를 사용해도 되고, 소문자를 사용해도 됩니다.  즉, "c30"을 사용하나 "C30"을 사용하나 동일합니다.

6)

Set xlsStable = Nothing

 

Set xlsUnit = Nothing

dll 이나 ocx를 변수로 선언해 사용하면 메모리를 차지해 컴퓨터 속도가 느려진다고 합니다.  그래서 위와 같이 Nothing을 설정해, 변수가 차지하고 있는 메모리를 해제해 줍니다.  요즈음은, 컴퓨터 속도가 빨라서 큰 문제는 없을 것 같은데, 하여튼 해제해 줍니다.

 

 

3.3 Private Sub Worksheet_Change(ByVal Target As Excel.Range)

Worksheet_Change 이벤트는 해당 Worksheet의 셀 값이 변경될 때 발생합니다.  Target은 바뀐 셀을 나타내는 Range 개체입니다.  예를 들어, C7 셀의 값이 바뀌었다면, Target은 Range("C7")입니다. 만일 C7셀과 F10으로 이루어진 사각형 범위의 셀 값이 변경되었다면, Target은 Range("C7:F10")으로 범위를 나타냅니다.

앞에서의 엑셀 시트 디자인에서 노란색 셀 값이 변경될 때 실행될 코드를 이곳 Worksheet_Change 이벤트에 코딩합니다.

셀 값의 변경은, 셀에 사용자가 값을 직접 입력하거나 혹은 VBA 코딩에서 셀에 값을 입력할 때 발생합니다.  VBA 코딩에서 셀에 값을 입력한다는 것은, 예를 들어 Range("c7") = 7 과 같은 코드를 실행하는 것입니다.

하지만, 셀 내부의 공식에 의해 셀 값이 변경될 때는 Change 이벤트는 발생하지 않습니다.  그리고, 셀 값을 삭제할 때도 Change 이벤트는 발생하지 않습니다.

1)

On Error GoTo CheckError

 

 

 

Exit Sub

 

CheckError:

 

MsgBox Err.Description

On Error GoTo 문은 해당 프로시저 실행 중간에 오류가 발생하면 어디로 가라는 문장입니다.

VBA에서 어느 지점을 표시하고자 할 때는, 어느 지점에 해당 지점을 표시하는 단어를 타이핑해 넣은 다음, 단어 뒤에 ":"(콜론)을 타이핑하면 됩니다.  위 문장에서는 어느 지점을 CheckError라고 명명하였으며, 프로시저 맨 끝 부분에 위치시켰습니다.  그리고 On Error GoTo 문 다음에 CheckError를 타이핑해서 오류 발생 시에 CheckError 지점으로 가도록 하였습니다.   CheckError 라는 명칭은 다른 이름으로 바꾸어도 됩니다.

CheckError 지점 바로 앞에는 Exit Sub라는 문장을 두어서, 오류가 발생하지 않고 CheckError 지점 전까지의 코드가 제대로 실행된 경우에는 프로시저를 빠져 나가도록해야 합니다.  Exit Sub 문은 Sub 프로시저를 빠져 나가라는 문장입니다.

CheckError 지점 다음에는 오류 처리 코드를 기술합니다.  여기서는 특별한 처리를 하지 않고, 오류 설명을 메시지 박스로 사용자에게 표시하도록 하였습니다.   MsgBox 문은 코드 실행 중에 사용자에게 메시지를 표시해주는 문장으로, 자주 사용하는 문장 중에 하나입니다.  Err 문은 Error 개체를 나타냅니다.   코딩 창에서 Err을 타이핑하고 "."을 타이핑하면 Err 개체에서 사용할 수 있는 속성과 메소드가 자동으로 나열됩니다.  Err 개체의 Description 속성은 오류의 설명을 담고 있는 속성입니다.

위와 같이 Err.Description 문장 다음에 아무런 MsgBox 인수(Argument)가 없으면 메시지 박스에는 [확인] 단추만 나타납니다.  메시지 박스에는 필요에 따라서 여러 종류의 단추를 나타낼 수 있습니다.  MsgBox [Prompt], vbYesNo 라고 적으면, 메시지 박스에는 [예], [아니오] 2개의 단추가 나타납니다.  MsgBox의 자세한 사용번에 대해서는 도움말을 참조하시기 바랍니다.

2)

Dim CondRange As Range, SteamRange As Range, SizeRange As Range

 

Dim InputRange As Range

 

 

 

Set CondRange = Range("e11", "e12")

 

Set SteamRange = Range("i6")

 

Set SizeRange = Range("f23:f24")

 

 

 

Set InputRange = Union(CondRange, SteamRange, SizeRange)

위의 문장은, 앞에서의 엑셀 시트 디자인에서 노란색 셀을 궁극적으로 InputRange라는 변수에 지정하는 문장입니다.

첫 번째와 두 번째 줄의 문장은 CondRange와 SteamRange, SizeRange, InputRange라는 변수를 Range 개체로 선언한 것입니다.  동 변수들은 프로시저 내부에서 선언된 변수이므로 프로시저 변수이며, 본 프로시저 내부에서만 유효합니다.  다른 프로시저에서는 동 변수들이 존재하는지를 모릅니다.  다른 프로시저에서 동일한 변수를 다시 선언해서 사용해도 전혀 문제가 안됩니다.  프로시저 변수들은 해당 프로시저 내부에서만 유효하기 때문입니다.

세 번째, 네 번째 및 다섯 번째 문장은 노란색 입력 셀을 CondRange 개체 변수와 SteamRange 개체 변수, SizeRange 개체 변수에 입력하는 문장입니다.

여섯 번째 문장은 이들 세 Range 개체 변수들을 Union 메소드를 사용해 하나의 Range 개체로 만들어 InputRange 개체 변수에 입력하는 문장입니다.

위 문장은 Union 메소드를 사용하는 방법을 보여주기 위해 작성한 문장이며, 위의 전체 문장을 아래와 같이 2개의 문장으로 만들 수도 있습니다.

Dim InputRange as Range

Set InputRange = Range("e11:e12, i6, f23:f24")

위의 여섯 문장 대신에 위의 두 문장을 넣어서 실행해 보시기 바랍니다.    

3)

If Intersect(Target, InputRange) Is Nothing Then Exit Sub

이 문장은, 사용자가 변경한 셀(Target)이 InputRange 개체 변수에 입력된 셀들과 만나지(Intersect) 않으면(Nothing), Sub 프로시저를 나가라는(Exit Sub) 문장입니다.

아주 쉽죠.  그냥 영어 문장 쓰듯이 쓰면 됩니다.  이것이 Visual Basic의 장점입니다.   예전에는 실행 속도가 늦고 기능도 제한적이었던 것이 Basic이었었는데, 이제 Visual Basic이 속도나 기능면에서 Visual C++에 뒤떨어지지 않고, 프로그래머들이 가장 많이 사용하는 프로그래밍 언어가 되었습니다.

4)

Rem 계산 시작

이 문장은 실행이 되지 않는 주석(Remark) 문장입니다.   문장 앞에 Rem 이나 '(인용 부호)를 타이핑해 넣으면, 해당 문장은 주석 문장이 되어 실행이 되지 않습니다.   코딩할 때 주석을 달아 놓으면 나중에 수정할 때 많은 도움이 되겠지요.  주석 문장은 아무리 많아도 실행 속도에는 영향을 주지 않는다고 합니다.   원하는 만큼 주석을 달아도 됩니다.  주석 문장으로 만들면 글씨가 자동으로 녹색으로 바뀝니다.

문장을 테스트할 때, 다음에 사용하기 위해 지우고 싶지 않을 때에는, 해당 문장 앞에 인용 부호를 타이핑해 넣어서 주석 문장으로 만들어 놓은 다음, 필요할 때 인용 부호를 제거하면 다시 실행 문장으로 사용할 수 있습니다.  위와 같이 한글 문장을 주석 문장으로 사용할 수도 있습니다.

5)

Application.EnableEvents = False

Application 개체는 하나의 프로그램을 지칭하는 보통 명사로 볼 수 있습니다.  엑셀에서 사용되면 Excel 프로그램을 의미하며, 워드에서 사용되면 Word 프로그램을 의미합니다.  여기서의 Application은 엑셀 프로그램입니다.

엑셀 Application 개체의 속성 가운데 EnableEvents 속성은, 이벤트를 활성화시키거나 비 활성화시키는 속성입니다.  EnableEvents = Flase 로 설정하면 이벤트가 비 활성화되어서 이벤트 Sub 프로시저들의 코드가 이벤트가 발생해도 실행되지 않습니다.

계산 코드 가운데 계산된 값을 셀에 입력하는 문장이 있는데, 이러한 문장은 Worksheet_Change 이벤트를 발생시킵니다.  계산하는 동안에는 이벤트를 실행할 필요가 없는데, 계산된 값을 입력하는 문장에 의해 불필요하게 Worksheet_Change 이벤트가 발행하므로, 이러한 Worksheet_Change 이벤트를 발생시키지 않게 하기 위하여 모든 이벤트를 비 활성화시키는 것입니다.

계산이 다 끝나면 이벤트를 다시 활성화시킬 것입니다.

6)

'Check input error

 

If Range("e11") <= Range("i6") Then

 

    MsgBox "Saturated condensate pressure should be higher than flash steam pressure.", vbCritical

 

    Exit Sub

 

End If

If ... then... End If 의 조건문입니다.

'Check input error는 주석문입니다.  앞으로 주석문은 설명하지 않겠습니다.

두 번째 문장은, 만일(If) "E11" 셀 값(Flash Tank로 유입되는 고압 응축수의 압력)이 "I6" 셀 값(Flash 증기 압력)보다 같거나 작으면, 이라는 문장입니다.  고압 응축수 압력이 Flash 증기 압력보다 같으면, 계산에서 영으로 나누었다는 오류가 발생하거나(같은 경우), 유량 값들이 마이너스(-) 값으로(작은 경우) 계산됩니다.

세 번째 문장은 경고문을 사용자에게 띄우는 MsgBox 문입니다.  vbCritical 이므로, MsgBox에 더 이상 진행할 수 없다는 의미의 "X" 표시가 함께 나타납니다.

네 번째 문장은 Sub 프로지저를 나가라는 문장입니다.  즉 더 이상 진행하지 말고 그냥 나가라는 의미입니다.

다섯 번째 문장은 If 문의 끝이라는 의미의 문장입니다.  즉 여기까지가 If이 발생하면 실행할 코드의 끝이라는 의미입니다.

앞서의 3) 번 문장에서와 같이 If ... Then 의 조건문을 하나의 문장으로 쓰는 경우에는, End If 문이 필요 없으나, If ... Then 조건에 의해 수행할 코드를 여러 문장으로 쓰는 경우에는, 여기가 조건 문의 끝이라는 의미의 End If 문을 써 주어야 합니다.

엔지니어링 프로그래밍을 할 때, 항상 계산 상에서 오류를 일으킬 내용이 무엇인가 생각하여, 이와 같이 오류를 처리하는 코딩을 해주는 것이 좋습니다.

 

그 다음의 Set 문장들과 xlsStable 과 xlsUnit 의 단위 설정 문장은, 앞서의 3.2 Private Sub Worksheet_Activate() 이벤트 의 문장과 동일합니다.  이곳에서 이들 클래스 모듈을 본격적으로 사용해야 하니까, 다시 설정해 주는 것입니다.   여기서의 단위 설정이 3.2 Private Sub Worksheet_Activate() 이벤트 에서의 단위 설정과 동일해야, 엑셀 시트에 표시되는 단위와 실제로 계산에 사용되는 단위가 동일해지겠지요.

자, 이제 본격적으로 엔지니어링 계산 코딩을 시작합니다.

7)

'Condensate

 

Dim CondPress As Single, CondEnth As Single

 

CondPress = Range("e11")

 

 

 

xlsStable.SSTABLE 1, CondPress

 

 

 

Range("f11") = xlsStable.TSAT 'Cond saturation temp

 

Range("f12") = xlsStable.ENTHF 'Cond saturated water enthalpy

 

 

 

CondEnth = xlsStable.ENTHF

위 문장들은, 사용자가 입력한 고압 응출수의 압력을 읽어서 온도와 엔탈피 등을 증기표로부터 읽어 필요한 곳에 입력하는 문장들입니다.

즉, 셀 "e11"에 사용자가 입력한 고압 응축수의 압력을 읽어서, 증기표에서 온도와 엔탈피를 구해, 셀 "f11"과 셀 "f12"에 각각 입력하고, 변수 CondEnth에 입력하는 문장입니다.  변수 CondEnth에 엔탈피 값을 입력한 목적은, 다음 계산에서 사용하기 위한 것입니다.

첫 번째 문장은 CondPress와 CondEnth 라는 변수를 단정도 실수(Single)로 선언하는 문장입니다.  여러 변수를 하나의 Dim 문장으로 선언할 때, ","로 분리해선 선언하면 됩니다.

두 번째 문장은 셀 "e11"의 값을 읽어서 CondPress 변수에 입력하는 문장입니다.  즉 사용자가 입력한 고압 응축수 압력 값을 읽어서 CondPress 라는 변수에 입력한 것입니다.

세 번째 문장은 xlsStable 개체의 SSTABLE 메소드를 사용해 압력 CondPress에서의 포화 증기표를 찾는 문장입니다.  

xlsStable을 타이핑한 후 "."을 치면, xlsStable에서 사용할 수 있는 속성과 메소드가 나열됩니다. 그 가운데 SSTABLE이 포화 증기표를 찾는 메소드입니다.

그 다음에 한 칸을 스페이스 바(Space Bar)를 쳐서 띄우면, "AKSAT As enmSStable" 이라는 문구가 표시되는데, 이는 입력할 성질이 무엇인지, 즉 무슨 성질을 가지고 포화 증기표를 찾을지를 나타내는 인수(Argument)입니다.  "1"을 입력하면 "압력" 값을 가지고 포화 증기표를 찾겠다는 의미이며, "2"를 입력하면 "온도" 값을 가지고 포화 증기표를 찾겠다는 의미입니다.  

여기서는 CondPress라는 압력 값을 가지고 포화 증기표를 찾을 것이미로, "1"을 입력했습니다.  컴퓨터에 따라서는 사용할 수 있는 인수가 나열되기도 합니다.  그럴 경우에는 나열된 인수 가운데 하나를 선택해서 사용할 수도 있습니다.  하지만, 그렇게 코딩한 엑셀 파일을 인수가 나열되지 않는 컴퓨터에서 사용할 경우 오류가 발생하므로, 인수가 나열되더라고 1이나 2를 직접 입력할 것을 권장합니다.

"1"을 입력한 다음에 ","를 타이핑하면 "ARGSAT As Single" 이라는 문구가 표시되는데, 이는 찾고자하는 성질의 값을 나타내는 인수입니다.  여기서는 찾고자하는 압력 값이 CondPress 라는 변수에 입력되어 있으므로, CondPress를 입력했습니다.

이렇게 작성된 xlsStable.SSTABLE 1, CondPress 코드가 실행되면, xlsStable 클래스 모듈은 압력 CondPress에서의 각종 성질을 계산해 xlsStable의 속성 값으로 되돌려 줍니다.   SSTABLE 메소드가 되돌려 주는 xlsStable 속성 값은 다음과 같습니다.

PSAT : 포화 압력

TSAT : 포화 온도

SVOLF : 포화 수 비체적

SVOLF : 포화 증기 비체적

ENTHF : 포화 수 엔탈피

ENTHF : 포화 수 엔탈피

ENTROF : 포화 수 엔트로피

ENTROF : 포화 수 엔트로피

VISCOF : 포화 수 절대 점도

VISCOF : 포화 수 절대 점도

VISCOXF : 포화 수 동 점도

VISCOXF : 포화 수 동 점도

세 번째와 네 번째 문장은 xlsStable.SSTABLE 1, CondPress 코드 실행에 의해 계산된 포화 증기 성질 가운데, 포화 온도 값(TSAT)과 포화 수 엔탈피 값(ENTHF) 값을 셀 f11"과 셀 "f12"에 각각 입력하는 문장입니다.

다섯 번째 문장은, CondEnth 변수에 포화 수 엔탈피 값을 입력하는 문장입니다.   포화 수 엔탈피 값은 다음의 계산에서 사용될 예정인데, 다음에 계산할 때 이렇게 변수에 입력해 사용하는 대신에, 셀 "f12" 값을 바로 읽어서 계산하는 방법도 있습니다.  하지만, 이렇게 변수에 입력해 변수를 사용하면, 대신에 변수에 입력해 사용하는 이유는 나중에 입력 셀의 위치를 변경하는 경우, 코드의 수정을 쉽게하기 위한 것입니다.

8)

'Flash and drain

 

Dim FlashPress As Single, FlashSVOL As Single

 

Dim FlashEnth As Single, DrainEnth As Single

 

 

 

FlashPress = Range("i6")

 

 

 

xlsStable.SSTABLE 1, FlashPress

 

 

 

Range("j6") = xlsStable.TSAT 'Flash and drain saturation temp

 

Range("j7") = xlsStable.ENTHG 'Flash saturated steam enthalpy

 

Range("j27") = xlsStable.ENTHF 'Drain saturated water enthalpy

 

 

 

FlashEnth = xlsStable.ENTHG

 

DrainEnth = xlsStable.ENTHF

 

FlashSVOL = xlsStable.SVOLG 'Flash saturated steam specific volume

위 문장들은, Flash Tank 내부의 압력을 읽어서, 증기표로부터 각종 성질을 찾아, Flash Steam과 Drain에 해당하는 셀들과 변수들에 해당 성질을 입력하는 문장들입니다.

Flsh Tank로부터 분리되어 배출되는 강제 증발 증기(Flash Steam)와 배수(Drain)은 각각 Flash Tank 내부 압력에서의 포화 증기(Saturated Steam)와 포화 수(Saturated Water)입니다.   Flash Tank의 Vent Pipe 입구의 압력과 Flash Tank 내부 압력은 동일하므로(압력 차이를 무시할 수 있음.), 사용자로 하여금 Vent Pipe 입구의 압력을 입력토록 한 후 동 압력을 Flash Tank 내부 압력으로 가정하였습니다.

첫 번째와 두 번째 문장에서 필요한 변수들을 선언하고, 세 번째 문장에서 셀 "i6"의 Flash Steam 압력을 변수 FlashSteam으로 읽어 들인 후, 네 번째 문장에서 읽어 들인 FlashSteam 압력으로 포화 증기표(xlsStable.SSTABLE)를 찾았습니다.

찾은 포화 증기 성질 가운데, 다섯 번째 문장에서 Flash Steam의 온도 셀인 "j6"에 포화 온도(TSAT)를 입력하고, 여섯 번째 문장에서 Flash Steam의 엔탈피 셀인 "j7"에 포화 증기 엔탈피(ENTHG)를 입력하고, 일곱 번째 문장에서는 Drain의 엔탈피 셀인 "j27"에 포화 수 엔탈피(ENTHF)를 입력하였습니다.  Drain의 온도 셀인 ""j26"에도 포화 온도를 입력해야 하는데, VBA를 이용하는 대신 엑셀 시트에서 셀 함수(= j6)를 이용해 입력하였습니다.

여덟 번째 문장 이후에서는 다음의 계산에서 사용할 값들을 변수 FlashEnth, DrainEnth, FlashSVOL 에 입력하였습니다.

9)

'Flow calculation

 

Dim CondFlow As Single

 

Dim FlashFlow As Single, DrainFlow As Single

 

 

 

CondFlow = Range("e12")

 

 

 

FlashFlow = CondFlow * (CondEnth - DrainEnth) / (FlashEnth - DrainEnth)

 

DrainFlow = CondFlow - FlashFlow

 

 

 

Range("i7") = FlashFlow

 

Range("i27") = DrainFlow

위 문장들은 이제까지 찾은 성질들과 사용자가 입력한 고압 응축수 유량으로부터 Flash Steam 유량과 Drain 유량을 계산하는 문장들입니다.

첫 번째와 두 번째 문장은 필요한 변수들을 선언하는 문장이며, 세 번째 문장은 사용자가 입력한 고압 응축수 유량이 들어 있는 셀 "e12"의 값을 읽어 들여 변수 CondFlow에 입력하는 문장입니다.

네 번째 문장은 앞에서 설명한 계산 공식에 따라 Flash Steam의 유량을 계산하는 문장입니다.  보시는 바와 같이, Visual Basic의 계산 문장은 일반 게산 문장과 거의 유사합니다.  특히, 엑셀 시트에서 계산 함수 쓰는 방법과 동일합니다.

다섯 번째 문장은, 질량 보존 법칙에 따라, 사용자가 입력한 고압 응축수 유량에서 Flash Steam 유량을 빼서 Drain 유량을 계산하는 문장입니다.

여섯 번째와 일곱 번째 문장은 계산된 Flash Steam 유량과 Drain 유량을, 셀 "i7"과 "i27"에 각각 입력하는 문장입니다.

10)

'Tank sizing

 

Dim FlashVel As Single, HWRatio As Single

 

 

 

FlashVel = Range("f23")

 

HWRatio = Range("f24")

 

 

 

'Conversion into metric units

 

Dim FlashVel_m As Single, FlashFlow_m As Single

 

Dim FlashSVOL_m As Single, Tankdia_m As Single

 

 

 

FlashVel_m = xlsUnit.CvtVel(xlsUnit.uVel, 0, FlashVel) 'm/sec

 

FlashFlow_m = xlsUnit.CvtMFlow(xlsUnit.uMFlow, 0, FlashFlow) 'kg/hr

 

FlashSVOL_m = xlsUnit.CvtSVOL(xlsUnit.uSVOL, 0, FlashSVOL) 'm3/kg

 

 

 

Tankdia_m = Sqr(FlashFlow_m * FlashSVOL_m / 3600 / FlashVel_m * 4 / 3.141592) 'meter

 

 

 

'Conversion into original units

 

Dim TankDia As Single, TankHt As Single

 

 

 

TankDia = xlsUnit.CvtLen(0, xlsUnit.uLen, Tankdia_m)

 

TankHt = TankDia * HWRatio

 

 

 

Range("f25") = TankDia

 

Range("f26") = TankHt

이번 문장들은 Flash Tank의 크기를 계산하는 문장들입니다.

첫 번째부터 세 번째 문장까지는 사용자가 입력한 Flash Tank 내부에서의 Flashing Velocity와 Tank의 높이/직경 비를 셀 "f23"과 "f24"에서 각각 읽어 들여, 변수 FlashVel과 HWRatio 에 입력하는 문장입니다.

단위를 바꿀 때마다 계산 문장을 변경하지 않으려면, 단위에 관계 없이 사용할 수 있는 계산 문장을 만들어야 합니다.  이러한 방법은, 계산 문장 내에서 어느 특정 단위로 계산을 한 다음, 다시 원래의 단위로 환산해 되돌리는 방법을 사용하면 됩니다.

네 번째와 다섯 번째 문장은 필요한 변수들을 선언하는 문장입니다.

일곱 번째 문장은 xlsUnit 개체의 CvtVel 메소드를 사용해, FlashVel의 단위를 "m/sec" 단위로 환산하는 문장입니다.

xlsUnit을 타이핑한 후 "."을 치면, xlsUnit에서 사용할 수 있는 속성과 메소드가 나열됩니다. 그 가운데 Cvt로 시작하는 메소드가 단위 환산 메소드인데, CvtVel 메소드가 속도 환산 메소드입니다.  

그 다음에 "("을 타이핑하면, "SourceUnit As enmVel" 이라는 문구가 표시되는데, 이는 원래의 단위가 무엇인지를 나타내는 인수(Argument)입니다.  앞에서 xlsUnit.uVel = chyunit_mpersec 라는 문장으로 xlsUnit 개체의 단위를 설정하였습니다.  즉 xlsUnit 개체의 uVel 속성이 xlsUnit의 속도 단위를 보관하는 속성입니다.  그러므로 원래의 단위(Original Unit)는, 그 단위가 무엇이던 간에, xlsUnit.uVel 속성에 담겨져 있는 것입니다.  그러므로, "SourceUnit As enmVel" 인수 자리에 xlsUnit.uVel을 입력합니다.

그 다음에 ","를 타이핑하면 "TargetUnit As enmVel" 이라는 문구가 표시되는데, 이는 환산하고자 하는 목표 단위가 무엇인지를 나타내는 인수입니다.  xlsUnit 개체의 단위 인수 값들은 다음과 같습니다.

속도(uVel)

 

 

0 : m/sec

1 : ft/sec

2 : kilo m/hr

3 : Metric knot

4 : US mile/hr

5 : UK knot

길이(uLen)

 

0 : m

1 : ft

2 : mm

3 : cm

4 : km

5 : inch

6 : yard

7 : US mile

8 : Nautical mile

비체적(uSVOL)

 

0 : m3/kg

1 : ft3/lb

2 : cm3/g

3 : inch3/lb

4 : US gal/lb

5 : UK gal/lb

질량 유량(uMFlow)

 

0 : kg/hr

1 : lb/hr

2 : kg/sec

3 : lb/sec

4 : Metric ton/hr

5 : US ton/hr

6 : UK ton/hr

 

 

 m/sec 단위로 바꾸어서 계산할 계획이므로, "TargetUnit as enmVel" 인수 자리에 m/sec 단위를 나타내는 "0'을 입력합니다.

그 다음에 ","를 타이핑하면 "SourceValue As Single" 이라는 문구가 표시되는데, 이는 환산하려는 원래의 값을 나타내는 인수입니다.  FlashVel을 환산하려고 하므로 FlashVel 을 입력합니다.

xlsUnit 개체의 모든 단위 환산 메소드들은 Function 메소드들입니다.  즉 그 메소드 이름 자체에 환산된 값을 되돌려 주는 메소드들입니다.  그러므로 위의 문장에서와 같이, 환산된 m/sec 단위의 속도를 입력할 변수 FlashVel_m 에 xlsUnit.CvtVel 메소드를 그대로 "="로 입력하면 됩니다.

여덟 번째 문장은 FlashFlow을 kg/hr 단위로 환산해서 변수 FlashFlow_m 에 입력하는 문장이며, 아홉 번째 문장은 FlashSVOL을 m3/kg 단위로 환산해 FlashSVOL_m에 입력하는 문장입니다.

열 번째 문장은 Sqr 함수를 이용해 Tank Diameter를 계산해서 변수 Tankdia_m에 입력하는 문장입니다.

열 한 번째 문장은 필요한 변수를 선언하는 문장이며, 그 다음 문장은 m/sec 단위의 Tankdia_m을 원래의 단위로 환산하는 문장으로, SourceUnit와 TargetUnit가 바뀐 것을 알 수 있습니다.

그 다음 문장들은 Tank Height를 계산하고, 계산된 값들을 해당 셀에 입력하는 문장들입니다.

11)

Application.EnableEvents = True

 

 

 

Set xlsStable = Nothing

 

Set xlsUnit = Nothing

이들 문장들은 계산을 마무리 하는 문장들입니다.

첫 번째 문장은 이벤트에 다시 활성화시키는 문장이며, 그 다음 문장들은 xlsStable 개체와 xlsUnit 개체를 메모리로부터 삭제하는 문장들입니다.

 

맺음 말

이제까지의 설명을 보면, 사실 어려운 내용이 크게 없습니다.  간단한 VBA 언어의 규칙과 ESCommon 개체의 클래스 모듈의 사용법만 알면, 엑셀의 사용 범위를 한 차원 높일 수 있습니다.  한번 익숙해지는 것이 힘들지, 일단 익숙해지면 그다지 어려운 일은 아닙니다.

앞으로의 강의에서는, 이번 강의에서 설명된 내용에 대한 설명은 생략하고, 주로 새로 소개되는 부분에 대한 설명만을 하도록 하겠습니다.  익숙해지기 전까지는, 이번 강의를 자주 참조하시기 바랍니다.

다음 강의에서는, 위의 Flash Tank 계산을 계산서 문서로 출력할 수 있는 엑셀 VBA를 작성할 계획입니다.(끝)

 


Copyright (c) 2004 ENGSoft Inc., Seoul, Korea, All right reserved.