애들센스


Equity Swap이란? 증권

(흑우 동생) : '형! 요즘 주식 뭘 사야해~'
(사짜 형님) : '야~ 주식 사지마~ 내가 갖고 있는 주식으로 얻는 매매차익, 배당 등을 너한테 줄 테니까
대신 그 돈에서 예금해두고 이자 나오는 거 나한테 줘라'.
(흑우 동생) : 이게 뭔 사기꾼 같은 소리야~
(사짜 형님) : '주식 사고팔면 수수료 나가고 팔때 세금 나가잖아. 그리고 형이 종목을 잘 고르잖아. 그리고 난 롱숏 전략도 사용할 수 있어! 게다가 형 말처럼 하면 수수료/세금을 절약하고 좋잖아'
(흑우 동생) : 흠 설득력 있네. 설마 흑우가 되는 건 아니지?

에쿼티 스왑을 쉽게 설명하자면 대충 이런 내용이다. 사실 제비용을 뺀 금액을 교환하는 것이지만... Equity Swap이란 미래에 정해진 시점에 기초자산에서 발생하는 현금흐름과 기초자산을 매수기 위한 담보에서 발생하는 수익을 교환하는 계약이다.

자세한 내용은 EquitySwap.pdf 에 ...

심심한 김에 회사에 재능기부?-월급 받잖아~ 오피스/VBA/Office.JS

많은 사람들이 매일 하는 단순작업을 자동화하는 것이 VBA인데, 그런 작업중 하나의 예를 가지고 최선의 VBA코드를 만들어 보려고 한다. 일단 개인적인 의견이지만 최선의 VBA코드는 코드를 되도록 줄이는 것이다. 아예 VBA코드가 없는 게 최선의 VBA프로그래밍이다. 이게 무슨 개똥같은 철학같은 소리이고 어불성설인가? 가지 많은 나무에 바람 잘 날 없다는 속담이 딱 들어 맞는다. 가령 아래와 같은 워크시트가 있는 데, 둘 다 같은 목적과 작업순서를 가진다.

B열의 값이 1.0 이상인 종목에 대하여 C~G열까지 복사하기
(이번 경우에는 C4:G8 (하이라이트 친 부분)이 복사할 셀영역이다)


I열의 값이 25.0 이상인 종목에 대하여 J~Q열까지 복사하기
(이번 경우에는 J4:G7 (하이라이트 친 부분)이 복사할 셀영역이다)


VBA 로 나름 최선의 코드를 만들면 다음과 같다.
Sub GapOver()
    On Error Resume Next
    Const CELL_BEGIN = "B4"
    Call CpyRange(Range(CELL_BEGIN), ">=1", 5)
End Sub

Sub BigPL()
    On Error Resume Next
    Const CELL_BEGIN = "I4"
    Call CpyRange(Range(CELL_BEGIN), ">=25", 8)
End Sub

Sub CpyRange(rngCrit As Range, strCrit As String, numCols As Long)
    Dim cnt As Long
   
    cnt = WorksheetFunction.CountIf(Range(rngCrit, rngCrit.End(xlDown)), strCrit)
    If cnt < 1 Then Exit Sub
    Range(rngCrit.Offset(0, 1), rngCrit.Offset(cnt, 0).Offset(-1, numCols)).Copy
End Sub
 같은 작업이므로 CpyRange() Sub프로시저를 공통으로 만들어 호출한다.
GapOver Sub 프로시저는 판단을 할 셀 영역의 시작부분과 판단기준, 복사할 컬럼의 수를 던져준다(Range(CELL_BEGIN), ">=1", 5)
마찬가지로 BigPL Sub 프로시저는 판단을 할 셀 영역의 시작부분과 판단기준, 복사할 컬럼의 수를 던져준다(Range(CELL_BEGIN), ">=25", 8)

이제 세 개의 매개변수를 넘겨받는 CpyRange() 프로시저는 조건에 맞는 셀의 갯수를 세어서 범위를 계산하고 복사한다. 이렇게 하면 일일이 셀 영역을 지정하여 복사하지 않고 버튼 하나만 누르면 자동으로 클립보드에 복사가 된다. 이후 붙여넣기는 알아서 쓰면 되는 거구...

그런데 코드를 더 줄일 수 있지 않을 까 하는 씰데없는 궁리를 해본다. 가장 중요한 기능-셀 영역을 판단하여 잡는 것-을 VBA가 아닌 엑셀로 할 수 있지 않나...그래서 고안한 아이디어는 OFFSET(), COUNTIF() 함수를 사용하여 셀영역에 이름을 붙이는 것이다.


수식 =OFFSET('일일 리스크관리'!$C$4,0,0,COUNTIF('일일 리스크관리'!$B$4:$B$53,">=1"),5)=OFFSET('일일 리스크관리'!$J$4,0,0,COUNTIF('일일 리스크관리'!$I$4:$I$53,">=25"),8) 는 COUNTIF()의 결과에 따라 동적인 셀 영역을 만들어 준다. COUNTIF()함수는 VBA 코드에서 사용한 바 있는 데, 조건을 만족하는 셀의 갯수를 돌려주는데, 이는 복사할 행의 갯수를 의미한다.

수식이 완성되었으므로 코드는 다시 더 줄어든다.
Sub GapOver()
    Range("종목과다").Copy
End Sub

Sub BigPL()
    Range("손익과다").Copy
End Sub

PS.무료로 간단한 매크로 만들어 드립니다. 대신 이 블로그의 글감으로 사용할 수 있습니다. 그러니 민감한 정보는 주지마세요.

건스앤로지스 Guns N' Roses - You could be Mine - Full Cover

깨방정스럽던 리드보컬 이름이 가물가물해졌지만 여전히 노래는 좋네요. 조만간 개봉할 터미네이터 다크페이트가 기대됩니다.

X 같은 XLOOKUP?

클리앙 새로운 소식 게시판에 가보니 XLOOKUP이라는 함수가 생기나 봅니다.
뭔가 욕같은 느낌이 드는 이름이지만 XLOOKUP이라는 함수가 추가될 예정인가 봅니다. 아직 제가 사용하는 엑셀에는 그런 함수가 없는 데, VLOOKUP의 단점을 보완해줄 느낌적인 느낌이군요. 자매품으로 XMATCH 함수도 있다는 군요.

이딴 거 말고 VBA 에 이어 또 다른 스크링팅 언어로 파이썬이나 자바스크립트(office.js가 있지만)를 엑셀에 낑겨 넣으면 좋겠습니다.


[원본 글] Announcing XLOOKUP

[클리앙]엑셀의 VLOOKUP, HLOOKUP을 대체할 XLOOKUP

[Mr.Excel]The VLOOKUP Slayer: XLOOKUP Debuts Excel

숫자판 자물쇠 열기 삽질의 추억



네 개의 비밀번호를 가진 숫자판 달린 자물쇠가 하나 있는 데, 이것 풀려면 몇 번 시도해봐야 할까?
순서는 상관없는 것으므로 조합이다. 8개중 4개를 뽑는 것이므로

8C4 = 8! / (8-4)!4! = 70

얼핏 기대한 것보다 의외로 가능한 조합이 적어 다행이다. 부작용이라면 쇠를 주물럭거리다보니 손에서 비린내가 나는 듯...

검색을 해보면 무식하게 일일이 70번 시도하는 게 아니라(운이 나쁘면 70번, 운이 좋으면 1번이지만) 자물쇠의 특성을 이용하여 아래의 URL과 같이 푸는 라이프해킹같은 방법도 있다.

[URL]누름식 비밀번호 자물쇠 푸는법 (밑에 열림버튼이 없을때)

생애 처음 빵을 만들어 보았다. 삽질의 추억

빵을 먹고 싶었다. 사먹느니 집에 묵히던 재료를 가지고 해보았다. 밥 공기 하나의 밀가루와 소금 이스트 설탕 버터를 가지고 빵을 만들어 보았다. 우유를 넣으면 좋치만 없으면 없는 대로...

계량스푼이 없어 티스폰으로 대충 넣었는데, 아무래도 이스트가 부족한 듯하다. 반죽이 그다지 부풀어 오르지 않았는데 계량컵과 식빵틀을 하나 장만해야겠다.


30분 오븐에 구웠지만 그닥 커지진 않는다.


원래 하려던 건, 아기 엉덩이같은 보들보들한 촉함에, 닭가슴살처럼 찢어지는 속살을 가진 식빵인데, 식빵틀이 없는 관계로 작은 빵으로 만들었다.


기대한 식감은 아니지만 나름 괜찮은 듯...딸기쨈이라도 있으면 딱 맞을 듯하다.





구글문서에게 받아쓰기 시키기 삽질의 추억

살다보니 별 일이 있기 마련이다. 컨퍼런스콜 녹음된 내용을 텍스트로 바꿔보라는 건데, 텍스트를 가지고 번역을 하는 서비스는 요즘 흔하고 품질도 좋아지는데, 의외로 음성을 텍스트로 바꾸어주는 서비스는 그닥 찾을 수 없다. 그래도 괜찮은 거 하나는 "음성 인식 서비스 (Watson Speech to Text)" 라는 건데, 생각외로 괜찮다.

다만 녹음파일의 크기가 커지면 제대로 작동하지 않는 에러가 생긴다. 그래서 꾸역 꾸역 녹음파일을 양념반, 후라이드반으로 나누었다.

이렇게 녹음파일을 올려서 텍스트로 변환하는 것은 드물고, 라이브로 마이크로 말하면 텍스트로 옮겨주는 서비스는 나름대로 있다. 그중에 우리에게 친숙한 구글문서--구글독스라고 하면 웬지 강아지가 생각나서--에 음성받아쓰기 기능이 있다.




그런데 얘를 써볼려니 , 마이크가 있는 PC에서 라이브로 궁시렁 거려야 한다. 그러나 방법이 없는 것은 아니다.

아래 그림과 같이 1)[녹음 장치]를 연후 2) 마우스 오른클릭을 하여 [사용할 수 없는 장치 표시]를 클릭하면 3) '스테레오 믹스'가 보이게 된다. 4) '스테리오 믹스'에 다시 마우스 오른클릭을 하여 '사용'으로 하고 , 5)이미 있던 멀쩡한 장치는 '사용 안함'으로 바꾼다.



이제 녹음파일을 플레이한 후 잽싸게 구글문서의 음성 받아쓰기를 클릭하고 , 녹음기 버튼을 눌러주면 위의 그림과 같이 알아서 바꿔준다. 바꾸어 준다고 했지..잘 바꾸어 준다는 말은 아니다. 아직 갈 길이 멀다.

근데 구글 클라우드플랫폼의 음성인식API를 서비스 하고 있고, 유튜브도 이걸 이용하여 자동자막을 해주는 것 같은데, 구글문서의 음성 받아쓰기는 유튜브의 자동자막수준보다 좀 떨어지는 것 같다. 자기네 클라우드플랫폼의 음성인식API를 사용할 것 같은데 말이지..

구글문서와 Watson Speech to Text를 비교하자면 둘 다 만족스러운 결과는 아니다. 다만 거둘뿐....

VBA 독재 물러가라~파이썬을 오피스로 모시기 작전 오피스/VBA/Office.JS

[우려낸 곰탕국물]
아시는 분이 거의 없으리라 생각되지만 excel.uservoice.com 이라는 게 있는데, 이름에서 알 수 있듯이 엑셀 사용자들의 민원을 듣기만 해주는 곳입니다. 여기에 'Python as an Excel scripting language'라는 민원이 있는 데, 한 마디로 'VBA 구리다~ 요즘 세상에 VB가 웬말이냐~ 파이썬을 달라~'는 내용입니다.

이와 관련된 새로운 포스팅을 보니, 팍팍 공감이 갑니다. 데스크탑 개발자도 사라지고 웹개발자만 있는 데, 누가 이딴 걸 배우겠습니까? 특히 개발로 생계를 이어가는 전문 개발자라면 말이죠. VBA는 뜻하지 않게 아마추어용이죠. 누가 안만들어주니 내가 배워, 내 업무에 써먹고 마는 가내수공업같은 이미지입니다.


사실 VBA를 다루지만, 이걸로 밥 먹고 살기는 힘듭니다. VBA가 문제가 아니라 업무자동화 또는 오피스 오토메이션(요즘은 비슷한 RPA라는 게 외국에선 인기입니다. 국내에서도 관련 서적이 나왔습니다. 모두를 위한 RPA 유아이패스 UiPath 입문 + 활용) 시장이 거지같은 거죠. 모든 애플리케이션이 웹으로 바뀌고 있어 데스크탑OS에서 돌아가는 애플리케이션의 전망은 조금씩 녹아내리는 빙하같은 거죠.

[옛날 곰탕국물]
지난 번 포스팅(뭐? python을 엑셀에서 사용할 수 있다고?)에서 엑셀 스크립트언어로서 파이썬이 채택될거라는 소문을 전해드렸는데, 오늘 오전에 office.com에서 사용자들의 의견을 전해주는 메일을 보내주었더군요.  메일 내용에 따르면 코멘트를 올린 사용자는 대기업에서 일하는데, 예전엔 엑셀로 많은 일을 해왔는데, 지금은 파이썬으로 그 일들을 대체하고 있다고 하네요.  그러나 파이썬이 엑셀 스크립팅 언어가 된다면 그런 추세가 반전될거라는 조언입니다. 그런 상황이 온다면 재미있는 일이 많이 생길 듯합니다. 일단 블로그 포스팅과 책을 써야 할 것 같군요. 그리고 엑셀을 이용한 기계학습/딥러닝도 돌려보고요..






주식 데이터 가져오기 오피스/VBA/Office.JS

'가능하다면 개발하지 말고 주변 소프트웨어를 잘 활용하자'는 게 게으른 아마추어 개발자의 대뇌상황이라 간단히 개발없이 KOSPI와 KOSDAQ지수를 가져오는 일을 궁리해보았다. 만만한 넘이 엑셀인데, 엑셀은 이미 완성형인데, 더더욱 완성형으로 가는 듯하다. [데이터]탭에서 보면 주식이나 지도를 가져오는 기능이 있다.

그런데 사용법을 몰라 MS 홈을 뒤져보니 미국주식의 예만 있고 한국주식관련된 예가 없어 몇 가지 찾아내었다.


'엑셀에서 주가 데이터 가져오기' 비슷한 검색어를 가지고 검색을 해보면 모두 비슷한 내용이다. 웹쿼리를 활용하는 방법. 남이 뭘 하든 신경끄고 엑셀의 새로운 기능을 익혀보는 데, 개별종목의 여러 정보는 구하는 데, 문제는 지수데이터에 대한 정보이다.
위의 그림에서 (?) 표시된 거래소코드(XKRX, XKOS) 뒤 지수티커에 대한 정보가 구하기 쉽지 않다. KQ11, SEU, KS100 등은 주식정보 사이트에서 사용하는 티커인데, 영 먹히질 않는 걸 보면 엑셀의 주식 데이터 기능이 종목만 제공하는 것일 지도 모르겠다.


파이썬 그림책-zip 파이썬/쟁고

zip함수를 그려 보았는데, 이해가 잘 되시나요?

오묘한 개발자의 세계-심각한 고민거리 삽질의 추억


엑셀 숫자 오름차순 정렬 질문드립니다 오피스/VBA/Office.JS

모 커뮤니티에 갔다가 다음과 같은 질문이 있길래 답변을 해주고 블로그로 옮겨 봅니다
안녕하세요. 엑셀 숫자 오름차순에 질문이 있어요..
엑셀 숫자가 오름차순을 하면

2018-2-100
2018-2-1000
2018-2-1001
2018-2-101

이렇게 되는데요ㅜㅜㅠ

2018-2-100 다음에 101이 나왔으면 좋겠거든요..
ㅠㅠㅠㅠ방법이 없을까요..?
감사합니다...도와주세요..

핵심은 데이터 길이가 같은 것끼리 정렬을 하게 해주는 것인듯 하다. 그래서 컬럼을 하나 추가해 LEN()함수로 길이를 구한 후, 1차 정렬기준으로 길이, 2차 정렬기준으로 데이터를 해주면 길이가 같은 데이터끼리 정렬되어 전체적으로 원하는 결과가 나온다.

(업데이트) VBA에서 본 이상한 코드들 오피스/VBA/Office.JS


VBA구문에 충실하게 FM대로 코딩하다가, 다른 사람들이 만든 코드를 보면 초보 입장에서 '이런 코드가 가능해?'하고 의문점을 가질 수 있는 걸 종종 보게 된다. VB/VBA는 c/c++, python, javascript 처럼 다양한 코드 스타일을 만들어 볼 수 있는 유연성이 떨어져 코딩하는 재미가 없는 편이다. 그러나 초보시절부터 현재까지 종종 생각하지 못한 코드를 보았는데, 오늘은 그걸 한번 정리해보려고 한다. 일단 생각나는 대로 적어 보자면:
(이 포스팅을 계속 업데이트 하려는 데, 최근 업데이트 내용을 선두에 두려고 한다. 예전 거는 그냥 두고...)

11. Join으로 배열의 값 한 번에 출력하기(2)(2019-07-01)
(앞서 팁10과 같은 연장선상의 내용이라 추가할까 하다가 아무래도 묻힐 것 같아 새로 번호를 붙입니다)
Join() 함수를 이용하여 배열을 내용을 여러 행으로 나누어 출력할 수 있다. 보통 For루프를 사용하여 출력을 하였다.
    arr = Array("문재인", "트럼프", "김정은", "남북미 정상회담", "토착왜구")
    Dim i As Long
   
    For i = LBound(arr) To UBound(arr)
        Debug.Print arr(i)
    Next
그러나 Join함수와 vbCrLf(캐리지-리턴,줄바꿈, 상수)를 사용하여 루프없이 출력할 수 있다.
arr = Array("문재인", "트럼프", "김정은", "남북미 정상회담", "토착왜구")
Debug.Print Join(arr, vbCrLf)


10. Join으로 배열의 값 한 번에 출력하기(1)(2019-05-26)
Join(배열, 구분자)

Join()함수는 주어진 구분자를 이용하여 문자들을 연결하는 함수이다. 가령 m이라는 배열을 다음과 같이 만들었다.
m = Array(1, 2, 3, 4)

이때 이를 출력하려면
Debug.Print m(0); m(1); m(2); m(3)

와 같이 할 것이다. 그러나 Join()함수를 다음과 같이 사용할 수 있다.
Debug.Print Join(m, ", ")

1. 고디바초코렛 사서 하나만 빼먹고 버림?
    Split("123,456,789", ",")(0)
위의 코드는 "123,456,789" 라는 문자열을 컴마(,)로 분리하는 split()함수 사용 예이다. 함수뒤에 (0)가 붙는 데, 분리한 결과의 첫 번째 항목을 가져오라는 의미이다. 보통은 그 결과를 변수로 받고 변수에서 인덱싱을 하여 결과를 가져오지만 이과정을 생략한 것이다. split()함수와 같이 배열을 돌려주는 함수라면 (0)와 같은 참조를 할 수 있다.
    Dim str As String
    Dim splited
   
    str = "123,456,789"
   
    Debug.Print Split(str, ",")(0)

2. Dim은 개무시?
    ReDim arr(10) As Long
ReDim()은 크기가 정해져 있지 않는 배열을 Dim으로 선언한 후 크기가 정해진후 사용하는 것이 보통이다. 하지만 그럴 필요없이 배열을 ReDim()으로 크기와 데이터형을 최초 선언할 수 있다.

3. 산 채로 잡아 꿀꺽?
    With Worksheets.Add
        .Name = "Sheet2"
    End With
또는
   Worksheets.Add.Name = "Sheet2"
개체를 추가하는 경우 With~End With구문을 이용하여 새로 추가한 개체에 대한 조작을 할 수 있다. Worksheets.Add의 경우 워크시트를 하나 추가하는 구문으로 보통 Set sht =Worksheets.Add와 같이 추가한 개체를 개체변수 에 할당하여 사용한다. 그러나 이 경우 추가와 동시에 변수에 할당하지 않고 바로 name속성을 부여한다. Worksheets.Add를 통해 만들어진 결과는 메모리에 있으며 With를 사용하여 할당된 메모리를 잡아둔 채 개체의 속성을 수정하고 있는 것이다.
1)번 예도 알고 보면 이런 식의 메커니즘이 작동하는 거으로 생각된다.

4. 여러 개를 한 방에 되돌려줌
    Function returnArray()
        returnArray = Array(123, 456, 789)
    End Function
Function프로시저는 보통 값을 하나만 돌려주는 걸로 알지만 배열을 돌려줄 수 있다. 함수 선언이 Function returnArray() As Long()같이 하여 이 함수가 배열을 돌려주는 걸로 미리 말할 수 있다. 그러나 그럴 필요없이 Array()함수를 사용하여 여러 종류의 값을 여러 개 돌려줄 수 있다.

5. 일단 두루와~
    Dim blnA As Boolean
    Dim blnB As Boolean
   
    Select Case True
    Case blnA = True
        Debug.Print "blnA is True"
    Case blnB = False
        Debug.Print "blnB is False"
    Case Else
        Debug.Print "blnA and blnB is not True and not False"
    End Select
Select Case 문은 하나의 변수를 상대로 하여 여러 가지 조건식을 검사하고 분기하는 명령이지만 Select Case True은 이상해 보인다. 무한루프를 돌리는 느낌처럼 변수의 자리에 'True'라는 불린(Boolean) 리터럴이 떡 하니 자리잡고 있다. 사실 중요한 판단분기 부분은 Case 부분이다. 보통 사용하는 Select Case가 하나의 변수만을 대상으로 조건판단을 하지만 이 경우 blnA 를 먼저 검사하고 이것이 통과되지 못하면 blnB를 다음 번에 검사하는 셈이 된다. 하나의 Select Case를 가지고 우선순위를 두고 여러 개의 변수를 차례로 검사하는 경우이다.

6. 어서 와~ 이런 셀 참조는 처음이지...
    Debug.Print WorksheetFunction.Sum([A2:A8])
   
    Dim rng As Range
   
    For Each rng In [A2:A8]
        Debug.Print rng.Address
    Next
VBA가 엑셀의 셀 범위를 참조하는 방식은 보통 Cells(행, 열), Range("셀 주소")와 같은 방식으로 하지만, []를 사용하여 현재 활성화된 시트의 셀 주소를 참조할 수 있다. 이것은 과거 VBA이전 매크로 시절의 유산(legacy)이라고 하는데, 아직도 잘 작동하고 있다. 그러면 궁금한 게 하나 더 생긴다. 셀 영역에 이름을 부여하고, 그 이름을 사용할 수 있지 않을 까?
가령 A2:A8X라고 이름을 만들면, 다음의 코드는 에러 없이 작동할 까?
    For Each rng In [X]
        Debug.Print rng.Address
    Next
물론 마찬가지로 작동한다. 하지만 상당히 신기해보인다.

7. '='는 '='가 아니다
    bln = A = B
하나 건너 '='가 나오는 위의 식은 간단하지만 생소했다. VB에서 '='는 할당 연산자이자 비교연산자이다. A = B는 변수 A와 변수 B가 같은 지 아닌지 를 묻는 비교연산이다. 이 결과는 bln에 할당하면서 'bln ='를 통해 할당연산자 '='를 사용한다.

8. Mid()야!, 네가 왜 거기에 있는 거야?
Mid()함수는 문자열의 중간에 있는 부분 문자열을 주어진 갯수만큼 돌려주는 함수이다. 얘도 함수이므로 당연히 '='를 사이에 두고 왼쪽에 Mid() 함수가 자리를 잡는다. 그런데 아래와 같이 이넘이 왼쪽으로 가고 그 자리엔 문자열이 떡하니 서 있다. 이게 무슨 짓인가?
    str = "The dog jumps"
   
    Mid(str, 5, 3) = "fox"
   
    Debug.Print str
위의 코드는 문자열 "The dog jumps"의 5번째 위치에 3개의 문자를 "fox"로 바꾸라는 의미이다. 문자열을 바꾸는 Replace()함수가 있지만 Mid()함수도 문자열을 바꿀 수 있다. 이렇게 바꾸면 "The fox jumps"로 문자열이 바뀌게 된다. 문자열의 갯수를 지정하는 length 매개변수는 그리 중요하지 않다. 즉
Mid(str, 5, 0) = "fox" 또는 Mid(str, 5, 9) = "fox"로 해도 Mid(str, 5, 3) = "fox"와 동일한 결과를 돌려준다. 바꿀 문자열("fox")의 갯수(3)가 더 중요하다.
다음의 경우는 어떠할 까?
    str = "New York"
   
    Mid(str, 5, 4) = "Mexico"
   
    Debug.Print str
그러면 Mid()의 절친인 Left()와 Right(), 얘네들도 가능할 까? 궁금해요?

(언제적 아재개그를 아직도 ㅠㅠ..)


9. 여러 개의 함수호출을 한 줄에 쓰기
함수는 값을 돌려주는 프로시저인데, 경우에 따라 결과값이 전혀 안궁금한 경우도 있다. 가령 Range 개체의 Replace()함수는 True/False를 돌려주는 데, 어떤 경우 셀값 치환(치질 아님)이 있으면 좋고 없어도 상관없다. 가령 주식포지션을 표시하는 데, 'Long'은 'L'로, 'Short'은 'S'로 간략하게 적는 게 깔끔하다. 이를 위해서는 Replace() 함수를 두 번 호출해야 한다.
    With rngPosition    
        Debug.Print .Replace("Long", "L"), .Replace("Short", "S")
    End With
Debug.Print가 결과값을 받을 변수 역할을 하는 데, Debug.Print는 여러 개의 변수를 사용할 수 있으므로 Replace()함수를 여러 번 사용하는 게 가능하게 되는 것이다.

없으면 빌려쓰는 ArrayList 오피스/VBA/Office.JS

VBA에는 남다른 철학이 있다. '없으면 빌어다 써라~'. 그런데 '한 푼 줍쑈~'라도 하려면 뭔가 있어야 하는데, 그것이 CreateObject()함수이다. CreateObject()함수를 사용하여 닷넷의 ArrayList를 빌어다 쓸 수 있는데, 다음은 ArrayList를 이용한 정렬이다.
Sub demoArrayList()
Dim it

With CreateObject("System.Collections.ArrayList")
For Each it In Array("aa1", "aa2", "aa3", "aa3", "aa2", "aa6")
.Add it: Next

'// 오름차순
.Sort
Debug.Print Join(.toarray, vbLf)
Debug.Print

'// 내림차순
.Sort
.Reverse
Debug.Print Join(.toarray, vbLf)
End With

End Sub
이를 이용하여 다음과 같이 워크시트의 셀 범위를 정렬할 수 있는 데
Sub demoSortArrayList()
Dim sn, j, jj, sp, ai
Dim bln As Boolean

sn = Sheet1.Range("B3:N18")

With CreateObject("System.Collections.Arraylist")
For j = 1 To UBound(sn)
.Add sn(j, 3)
Next

.Sort

sp = .ToArray
.Clear

For j = 0 To UBound(sp)
For jj = 1 To UBound(sn)
If sn(jj, 3) = sp(j) Then
.Add Application.Index(sn, jj)
sn(jj, 3) = ""
Exit For
End If
Next
Next

For j = 0 To .Count - 1
Sheet1.Range("B3:N18").Item(j + 1, 1).Resize(, UBound(sn, 2)) = .Item(j)
Next
End With
End Sub
사실 이렇게 복잡하게 할 필요는 없다. Range개체의 Sort메서드를 이용하는 것이 훨씬 간결하다. 응? 근데 왜 했지?
Sub demoSortRange()
With Sheet1.Range("B3:N18")
.Sort Key1:=.Item(1, 3), Order1:=XlSortOrder.xlDescending, Header:=xlNo
End With
End Sub

전혀 궁금하지 않은 자연상수e 펀드

연속복리를 이야기 하다가 공식( 원금*e^r )에 나오는 e 때문에 잠시 이야기가 새어 버리게 되었다. 오일러 상수 또는 자연상수 e 또는 자연로그의 밑 e의 값은 대충 ≈ 2.71828 18284 59045 23536 이다.

이 값은 복리계산에서 볼 수 있는 데, 가령 1년이라는 기간동안 복리횟수를 무식하게 늘리다 보면 이 숫자를 만나게 된다. 복리 계산식은 원금 A, 이율 r, 기간 n 일 때, S=A(1+r)^n이다.

가령 이율 100%로 1원을 예금한다고 하자.
* 1년후 이율이 100%, 기간은 1이므로
원금은 1*(1+100%)^1 = 1*(1+1)^1 = 2가 된다.
* 6개월 복리라면 이율은 100%÷2, 기간은 2이므로
원금은 1*(1+50%)^2 = 1*(1+0.5)^2 =2.25가 된다
* 분기 복리라면 이율은 100%÷4분기, 기간은 4이므로
원금은 1*(1+25%)^4 = 1*(1+0.25)^4 =2.4414가 된다
* 월 복리라면 이율은 100%÷12개월, 기간은 12이므로
원금은 1*(1+8.33%)^12 = 1*(1+0.0833)^12 =2.61207…가 된다
* 매주 복리라면 이율은 100%÷52주, 기간은 52이므로
원금은 1*(1+1.92%)^52 = 1*(1+0.0192)^52 =2.688373…가 된다
* 매일 복리라면 이율은 100%÷365일, 기간은 365이므로
원금은 1*(1+0.27%)^365 = 1*(1+0.0027)^365 =2.7146…가 된다
* 매시간마다 복리라면 이율은 100%÷8760시간, 기간은 8760이므로
원금은 1*(1+0.0114%)^8760 = 1*(1+0.000114)^8760 =2.714432…가 된다
* 매분마다 복리하면 이율은 100%÷525600분, 기간은 525600이므로
원금은 1*(1+0.00019%)^525600 = 1*(1+0.0000019)^525600 =2.71458…가 된다
* 매초마다 복리라면 이율은 100%÷31536000초, 기간은 31536000이므로
원금은 1*(1+0.0000032%)^31536000 = 1*(1+0.0000000317)^31536000 =2.71828…가 된다


타임버드: 복리횟수가 늘어날 수로 자연상수에 가까워지고 있다. 놀랍지 않은 가?

고문당하는 자: 전혀요~

타임버드: 밀리초, 나노초라면...?

고문당하는 자: 이제 고만 알아보자. 더 이상 안궁금하다. 오히려 이유없이 기분이 나빠질 뿐이다.


(수학)A light in a park can illuminate effectively up to a distance of 100m. 삽질의 추억

A light in a park can illuminate effectively up to a distance of 100m. A point on a bike path is 150m from the light. The sight line to the light makes an angle of 23˚ with the bike path. What length of the bike path, to the nearest metre, is effectively illuminated by the light?


(엑셀) 마지막 일자 구하기 오피스/VBA/Office.JS

이 팁을 알기 전에는 마지막 일자를 구하는 방법은 대충 이러했다.

어느 달의 마지막 일자를 구하려면
1) 한달을 더한 다음
2) 그 달의 1일을 날짜로 만들고
3) 다시 거기서 하루를 빼는 식
이었다.

그런데 다음과 같이 DATE()함수를 가지고 쉽게 구할 수 있다.
=DATE(year, month, 0)

일자를 0으로 두면 month의 이전 달 마지막 날짜를 가져온다. 즉 이전 달의 마지막 일자를 물어다 준다.

가령 6월이라면
=DATE(2019, 6, 0)은 '2019-05-31'을 돌려준다.

만일 1월이라면 어떨까?
=DATE(2019, 1, 0)은 '2018-12-31'을 돌려준다.

만일 month자리에 0을 넣으면?
=DATE(2019, 0, 0)은 '2018-11-30'을 돌려준다.
month=0으로 2019년의 직전월인 12월이 나오고 다시
day=0이므로 12월의 이전 달인 11월을 가리키는 것이다.

만일 month자리에 -1을 넣으면?
=DATE(2019, -1, 0)은 '2018-10-31'을 돌려준다.

즉 month자리에 0이하 값을 넣으면 이전 연도의 월을 가리키는 것이고
day 자리에 0을 넣으면 이전 달의 마지막 일자를 가져온다.

(업데이트)기하평균을 구하다가 에러를 만나다 증권

신심리지수나 Williams'R을 계산하다가 과열국면에서 침체국면 또는 침체국면에서 과열국면으로 지표값이 이동시 평균수익률이 어느 정도일까 궁금했다.


이때 사용하는 평균은 일반적으로 아는 산술평균이 아니라 기하평균이다. 산술평균은 "수치의 합계"를 "수치의 개수"로 나누지만 기하평균은 수치의 곱을 수치의 개수만큼의 제곱근을 취해 산출된다. 기하평균은 인구성장률이나 투자이율 등 성장률의 평균을 산출할 때 사용한다. 기하평균의 대표적인 예가 CAGR(Compound Average Growth Rate)이다 CAGR은 국가 GDP나 기업매출액의 성장률을 나타내는 수치이다.

엑셀에서는 다음과 같은 워크시트 함수나 수식을 사용할 수 있다.
  1. =GEOMEAN(datarange)

  2. =POWER(PRODUCT(datarange),(1/count(datarange)))

  3. {=EXP(AVERAGE(LN(datarange)))}
3번의 경우 배열수식이다.

그런데 수익률의 평균을 계산하려고 할때(수익률계산이 아니라 계산된 수익률들의 평균) 우리가 평소에 보던 방식(자산의 변동분을 비율로 표시하는 수익률)으로 계산한 수익율(-10%, +25% 등등)을 가지고 기하평균을 계산하려다 보니 문제가 생겼다. 수익률중 "0" 이하인 경우가 있는 경우 #NUM! 에러가 생긴다.

이는 루트안에 음수가 에러를 내기 때문이다. 기하평균은 (현재 값) : (이전 값) 비율을 가지고 계산한다. 이걸 the decimal multiplier equivalent values이라고 하는 데 우리 말로는 뭐라고 할 지 모르겠다.

현재값/이전값, 현재자산크기/이전자산크기와 같은 방식이 아니라 변동분의 비율(=평소 익숙한 표시방식의 수익률) 을 가지고 계산하는 경우 1 을 더하여 (기간만큼의) 제곱근을 계산한 후 앞서 더해 준 1을 다시 빼는 방식으로 하면 된다. 즉 아래 그림과 같다.

6%는 1.06이 되고 -3%는 0.97


이 된다. 다음은 엑셀에서 간단히 마이너스 수익률이 있는 데이터의 기하평균을 구하는 예이다.

심야의 걱정 삽질의 추억

통계 원고를 쓰는 중인데 내용이 쉽고 뻔해서 결국 내가 쓴 글이랑 남들이 쓴 글이랑 비슷하고 심지어 예제마저 소름끼칠 정도로 닮아서 베껴 쓴 것으로 보일 까 싶다.   분산과 표준편차를 1,2,3,4,5 다섯 개의 숫자로 예를 들어 쓰려고 긁적이는데, 나와 같은 생각을 가진 사람의 글을 보았다.
안본 눈 삽니다~

도박사의 오류(Gambler's Fallacy; Monte Carlo Fallacy)


어느 환자가 진료를 받고 있었다. 담당의사가 ‘이 병은 생존률이 1/100입니다.’ 그러자 환자가 깜짝 놀라면서 물었다. ‘그러면 저는 죽는 건가요?’ 의사는 느긋하게 대답한다. ‘그러나 걱정마세요. 당신은 완쾌될 것입니다. 그동안 이 병으로 나에게 진료받은 다른 99명의 환자가 죽었으니까요’

위의 이야기는 여러 가지 버전이 있는 데, 모두 도박사의 오류를 말하는 것이다. 도박사의 오류란:
서로 영향을 주지 않는 확률적 사건들속에서 그들간의 상관관계를 찾으려는 사고의 오류를 말한다. 서로 영향을 주지 않는 말은 독립적이라고 하는데, 즉 확률적 결과를 가지는 사건이 동일한 실행조건하에 반복시행하여 이번 사건의 발생이 다른 사건에 영향을 받거나 주지 않는 것이다.

동전을 던지는 경우 앞면과 뒷면이 나올 확률은 언제나 각각 1/2이며, 이번에 동전을 던지는 것이 이전 동전을 던진 결과와는 아무런 상관이 없다. 그러나 ‘앞서 동전을 10번 던져 앞면이 7번 나왔으니 이번에도 앞면이 나올 것이다’ 라고 판단하는 것이 도박사의 오류이다.

일상생활속에서도 볼 수 있는 도박사의 오류는 로또번호중 어느 번호가 가장 많이 나왔는 지 분석하는 것이다. 로또 추첨은 언제나 앞 회차와는 독립적이다.

'얘네들 미친 거 아냐!'

하는 생각을 잠시 했습니다. 2018년 결산이라니...지금 5월말인데, 거의 반 년이 지났는데 무슨 결산을 이제 하나 싶네요. 예전엔 연초에 한 듯 했는데...회사가 어렵나 싶네요.

이글루스가 초창기 블로깅 플랫폼이라는 상징성은 있었는데, 지금은 너무 낡아서 워드프레스로 옮겨야 하나 싶네요.  에디터도 낡고 스킨도 그렇고 구글광고 붙이는 것도 그렇고 이래저래 낡은 티가 팍팍 납니다.

그런데 예전에 플랫폼 옮기신 인기블로거분들이 다시 역이민오는 걸 보면, 손님이 블로거를 따라 가시는 건 아닌 듯합니다. 저 역시 다른 플랫폼으로 이민갈 생각을 궁리중인데, HOXY 따라 오실 분 있으세요? 절대 대표 블로거로 뽑히지 않아서 그런 건 아닙니다. ㅎㅎ

그래도 한 줌밖에 안되는 글을 찾아와 주시는 분들께 감사드립니다.

Exponential growth

If the population of a certain country is 1 billion and it is growing at 1.5%, find the population after 3 years.
1*e^(0.015*3)=e^0.045=1.046

A certain population is 60 million and it is growing at 3% continuous per annum. Find the population after 5 years.
Population is:
60*e^(5*0.03)=60*e^0.15=60*1.161834=69.7

If the growth multiple per annum is 1.16, find the continuous growth rate per annum.
e^r=1.16
ln e^r=ln 1.16
r*ln e = r = ln 1.16 = 14.842%

하스켈의 zipWith 함수 따라하기 오피스/VBA/Office.JS

함수형 프로그래밍 랭귀지인 Haskell의 Prelude모듈에는 zipWith()함수가 있는 데, 일단은 리스트를 받아서 리스트를 돌려주는 함수이다. 입력받은 리스트와 함수를 가지고, 각 리스트내 해당위치의 원소를 입력받은 함수에 적용한 결과를 리스트로 돌려준다. map함수와 유사하다.

하스켈의 zipWith() 함수 사용 예를 몇 가지 보면 짐작이 갈 것이다.
*[1,2,3]과 [3,2,1]의 원소를 연산자 + 에 적용하여 4,4,4,의 결과를 리스트로 만든다
Input: zipWith (+) [1,2,3] [3,2,1]
Output: [4,4,4]

*5가 10개인 리스트, (replicate 10 5)와 1~10까지 10개의 리스트, [1..10]를 가지고 5의 거듭제곱(**)을 계산한다
5^1, 5^2, 5^3, 5^4, 5^5, 5^6, 5^7, 5^8, 5^9, 5^10
Input: zipWith (**) (replicate 10 5) [1..10]
Output: [5.0,25.0,125.0,625.0,3125.0,15625.0,78125.0,390625.1,1.95313e+06,9.76563e+06]

* 리스트 [1..4]과 [5..8]를 가지고 2*x+y 식에 대입하여 계산결과를 리스트로 만들어 돌려준다.
Input: zipWith (\x y -> 2*x + y) [1..4] [5..8]
Output: [7,10,13,16]

다음은 VBA버전 zipWith함수이다.
Function ZipWith(f As String, A As Variant, B As Variant)
    'assumes that A,B are 1-dimensional variant arrays with the same bounds
    'and f is the name of a function with two variables
    Dim i As Long
    Dim m As Variant

    ReDim m(LBound(A) To UBound(A))
    For i = LBound(A) To UBound(A)
        Select Case f:
            Case "+":
                m(i) = A(i) + B(i)
            Case "-":
                m(i) = A(i) - B(i)
            Case "*":
                m(i) = A(i) * B(i)
            Case "/":
                m(i) = A(i) / B(i)
            Case "&":
                m(i) = A(i) & B(i)
            Case "^":
                m(i) = A(i) ^ B(i)
            Case Else:
                m(i) = Application.Run(f, A(i), B(i))
        End Select
    Next i
    ZipWith = m
End Function

Sub demoZip()
    Dim A As Variant, B As Variant, products As Variant

    A = Array(2, 3, 4)
    B = Array(5, 6, 7)
   
    products = ZipWith("*", A, B)

    Debug.Print Join(products, " ")
End Sub

VBA의 파이썬 따라잡기 오피스/VBA/Office.JS

파이썬의 map() 함수는 built-in 함수로 list 나 dictionary 와 같은 데이터를 받아 개별요소를 함수의 인자로 전달하여 결과를 list로 형태로 반환해 주는 함수이다. 글로 설명하면
def func(x):
  return x * 2
func()는 평범한 파이썬 함수로 매개변수로 받은 정수를 두배로 곱하여 반환해 주는 함수이다.
이 함수에 인자를 map() 함수를 이용해 전달해 보자.
>>> map( func, [1, 2, 3, 4] )
[2, 4, 6, 8]
위와 같이 map() 함수는 for문과 같은 반복문을 사용하지 않아도 지정한 함수로 매개변수를 여러 번 전달해 그 결과를 리스트로 뽑아 주는 유용한 함수이다. VBA는 이게 매우 부럽다. 남들은 한 줄로 간결하게 처리할 수 있는 데, VBA는 아직도 여러 줄의 반복문 블럭을 만들어야 한다. 그래서 흉내를 내보았다. 핵심은 빤스런 아니, Application.run() 이다.
Sub demoMap()
Dim m

m = map("func", Array(1, 2, 3, 4))

Debug.Print m(0); m(1); m(2); m(3);
End Sub

Function func(x)
func = x * 2
End Function

Function map(f As String, A As Variant) As Variant
'assumes that A is a 1-dimensional variant array
'and f is the name of a function that can be applied to it

Dim i As Long
Dim m As Variant

ReDim m(LBound(A) To UBound(A))
For i = LBound(A) To UBound(A)
m(i) = Application.Run(f, A(i))
Next
map = m
End Function
어떠신가? 그럴 듯 하지 아니한 가?


50만원이 100만원 되려면 몇 년이 걸릴 까? 펀드

이자율 1%일 때 50만원이 그 두 배인 100만원이 되려면 몇 년이 걸릴까? 아마 화성으로 우주선을 보내는 것이 더 빠를지도 모르겠다. n이 두 배가 되기 위해 필요한 시간(연)이라면 다음과 같이 식을 설정할 수 있다.

500000 * ( 1 + 0.01) ^n = 1000000

위의 식을 푸는 핵심은 양변에 로그를 씌우는 것이다. 그래서 아래와 같이 전개하면;
Log 500000 * ( 1 + 0.01) ^n = Log10^6
Log 1000000/2 + n * Log 1.01 = 6
Log 10^6 - Log 2 + n * Log 1.01 = 6
6 - Log 2 + n * Log 1.01 = 6
n * Log 1.01 = Log 2
n * (0.004321) = 0.30103
n = 69.66(년)

Log 값을 구하려면 계산기가 필요하지만, 그래도 눈에 가시같은 지수 n 을 쉽게 구할 수 있는 방법이다.

고인물같은 재무함수 낭비 방법 오피스/VBA/Office.JS

위키백과에서 정의한 현재가치는 미래에 얻게 될 확실한 부(富)의 가치를 현재의 가치로 환산한 값이다.
1기간 후부터 n기간까지의 미래에 일정한 현금흐름이 반복된다면 이를 현재가치로 환산하는 식은 다음과 같다.

엑셀의 PV함수 사용시 주의할 점은 매개변수중 pmt의 부호이다. pmt는 기간 동안 일정하게 지금 받거나 납입하는 금액을 말하는데, 현금이 들어오는 경우는 "+", 나가는 경우면 "-" 이다. 그리고 그 결과는 pmt의 부호방향과 반대이다.

가령 PV(0,1,-3) = 3, PV(0,1,3) = -3 이다.

그런데 PV공식을 보면 여러 개의 할인된 현금흐름(CF)이 ➕로 연결되어 있다. 만일 + 로 연결한 현금흐름에서 r=0이면 분모가 1이 되어 그 결과는 CF*n 이 된다. 결국 CF는 n기간동안 상수이고 , n 역시 상수이므로 단순곱셈이다. 그래서 3 곱하기 4는 12인데(구구단을 외우다니...처..천잰데..), PV를 이용하면 PV(0,3,4) = -12 이다. 엑셀의 PV함수 특성상 부호방향이 반대일 뿐이다. 즉 PV(0,1,1) = -1이고 PV(0,1,-1) = 1이다.

그래서 PV(0,1,PV(0,3,4))는 3 곱하기 4의 결과와 같다. 처음 나오는 PV는 부호를 변경하기 위한 것이고, 두 번째 PV는 곱셈연산을 한다. 곱셈을 참 어렵게 한다~ 그러나 현금흐름이 스칼라값이 아니라 배열이나 벡터와 같은 경우라면 한번에 여러 개의 곱셈연산을 하는 셈이 된다. 다음은 PV()를 이용하여 배열의 각 원소끼리 곱셈을 하는 코드이다.
Dim X, Y, Mult

X = Array(Array(1, 3), Array(2, 4))
Y = Array(1, 2)

With Application
    Mult = .PV(, 1, .PV(, X, Y))
End With
주의할 점은 Worksheetfunction.PV가 아니라 Application.PV를 사용해야 한다. Worksheetfunction.PV는 타입미스매치에러를 낸다.
위의 계산은 Y배열의 원소 1과 2를 배열 X내 1번째 배열 원소 1, 3에 곱하고, 다시 배열 X내 2번째 배열 원소 2, 4에 곱하는 것이다. 즉 원소대 원소 곱셈이다.
  • 배열Y 원소와 배열X의 1번째 배열원소간 곱셈 : 1*1, 2*3
  • 배열Y 원소와 배열X의 2번째 배열원소간 곱셈 : 1*2, 2*4
비슷한 방법으로 덧셈도 할 수 있다.
Add = .Pmt(, -1, X, Y)
그리고 다음과 같이 몇 가지 연산을 할 수 있는데, 머리 아프니 고만 알아보자.
연산
코드
X-Y
SLN(x, y, 1)
X/Y
SLN(x, y)
X^Y
Power(x, y)
X\Y
Quotient(x, y)
X=Y
Delta(x, y)
X<=Y
GeStep(x, y)

VBA 배열에 앙심을 품은 자 오피스/VBA/Office.JS

언제부터 인지는 모르겠지만 VBA 배열을 다루는 게 은근 재미있다. 그래서 어떻게 괴롭힐까 고민을 한다. 벡터연산이 없는 VBA을 갖고, 비스무리한 걸 만드는 데 ()희열을 느낄지도 모른다. 이른 바 VBA 변태~

몇 달 전에 스택오버플로 포스팅을 하나 북마크 해두고 나중에 봐야지 했는데, 이번에 코드를 함 뜯어 볼 참이다. 코드는 다음과 같다. 코드는 같은 길이, 같은 타입을 가진 두 개의 배열을 가지고 각 배열의 매칭되는 원소끼리 곱하는 짓거리이다.

코드의 핵심은
z = [GetX()*GetY()]

이다.

GetX()와 GetY()는 전역변수인 X, Y 배열을 돌려주는 역할만 한다. []는 'Square brackets'라고 부르는 데, 우리말로는 꺽쇠(마당쇠같은 머슴이름 아님). 이것은 벡터연산의 핵심인 Evaluate함수의 줄임말로 보면 된다.
expression.Evaluate (Name)
A formula or the name of the object, using the naming convention of Microsoft Excel.
The length of the name must be less than or equal to 255 characters.

[]는 셀 참조를 하는 용도로도 사용한다. 가령 A1 셀을 참조하기 위해서는 Range("A1")이라고 하지만 간단히 [A1]으로 써도 된다. A1과 "A1"은 다른 것이다. A1은 실제 해당 셀을 가리키는 개체상수 정도로 보면 되고, "A1"은 그냥 문자열 상수이다.

Evaluate()함수는 문자열로 전달한 수식이나 함수 등을 계산하는 함수이다.
여기에 들어갈 요소는 엑셀에서 사용가능한 것들, 문자열, 숫자, 배열상수, 연산자, 수식, 함수 등이다. 다음은 마이크로소프트 오피스데브센터에 있는 Evaluate() 사용 예이다.
[a1].Value = 25 
Evaluate("A1").Value = 25

trigVariable = [SIN(45)]
trigVariable = Evaluate("SIN(45)")

Set firstCellInSheet = Workbooks("BOOK1.XLS").Sheets(4).[A1]
Set firstCellInSheet = _
Workbooks("BOOK1.XLS").Sheets(4).Evaluate("A1")
[]안에 배열 X, Y를 직접 넣으면 되지 않을 까 싶지만, 이 배열변수들은 엑셀이 아닌 VBA의 요소이다. 따라서 변수를 넣으면 타입미스매치 에러가 난다.

GetX(), GetY()함수는 엑셀 워크시트에서도 사용가능한 요소이다. 그러므로 Evaluate()함수에서 사용가능한 것이고 둘 사이에 있는 * 는 곱셈연산자인데, 이것 역시 엑셀에서 통용되는 연산자 기호이다.

그래서 X,Y를 전역변수로 두고, 이 변수를 그대로 전달만 해주는 매개체이다. 얘네들은 Evaluate()함수에서 사용가능한 자격이 있기 때문이다.
Dim X, Y

Function GetX(): GetX = X: End Function
Function GetY(): GetY = Y: End Function

Sub MultiplyArrays()
Dim z

X = Array(1, 2, 3, 4, 5)
Y = Array(1, 2, 3, 4, 5)

' []가 과연 뭘까요?
' 변수 X, Y를 직접 사용하지 않고 GetX(), GetY() 함수를 사용할까요?
z = [GetX()*GetY()]

' 합계도 한번 구해 보고,
Debug.Print WorksheetFunction.Sum(z)

' 엑셀 워크시트로 출력도 해본다
Range("A1").Resize(UBound(X)) = WorksheetFunction.Transpose(X)
Range("B1").Resize(UBound(Y)) = WorksheetFunction.Transpose(Y)
Range("C1").Resize(UBound(z)) = WorksheetFunction.Transpose(z)
End Sub
예를 하나 더 보자.
이번에는 배열상수값을 사용한 예이다. {"Zip", "22150";"City", "Springfield"; "State", "VA"}는 엑셀에서 지원하는 상수포맷을 따른다. 마치 JSON개체처럼 보이지만 세미콜론(;)으로 행이 구분되고 컴마(,)로 컬럼이 구분되는 행렬형태의 2차원 배열상수이다.
Sub UsingSquareBrackets()
'The [...] syntax is a shortcut for Application.Evaluate()

Dim vArray As Variant
Dim iCounter As Long

' {}는 무엇일까?
vArray = [{"Zip", "22150";"City", "Springfield"; "State", "VA"}]

For iCounter = LBound(vArray, 1) To UBound(vArray, 1)
Debug.Print vArray(iCounter, 1), vArray(iCounter, 2)
Next

End Sub
Evaluate()함수를 사용하지 않는 경우 어떻게 할까? 위의 코드에서는 배열에 입력해야 하는 값들이 모두 상수여서 활용성이 떨어진다. 다음은 Evaluate()함수를 사용하지 않는 평범한 VBA코드이다. 코드가 약간 길어진다.
Sub UsingArrayInArray()
Dim vArray As Variant

Dim iZip As Long
Dim sCity As String
Dim sState As String

iZip = 22150
sCity = "Springfield"
sState = "VA"
vArray = Array(Array("Zip", iZip), Array("City", sCity), Array("State", sState))

Dim iCounter As Long

For iCounter = LBound(vArray, 1) To UBound(vArray, 1)
Debug.Print vArray(iCounter)(0), vArray(iCounter)(1)
Next

End Sub

쟁고파이썬쉘을 좀 더 편하게 사용하기 파이썬/쟁고


어드민 사이트는 UI화면을 통해 사용자가 CRUD(Create, Read, Update, Delete)를 편하게 작업할 수 있게 해주지만, 다양한 데이터 관리를 위해서는 쟁고파이썬쉘을 이용하는 것이 편리하다. 특히 뷰를 작성하기 위한 테스트 코드를 작성할 때 유용한데, 쟁고파이썬쉘은 manage.py에서 정의한 DJANGO-SETTINGS_MODULE속성을 이용하여 미리 settings.py 모듈을 임포트한다.

다만 문제라면 >>> 프롬프트에서 작업하는 것이 고역이다. 그래서 스택오버플로에서 찾아보니 다분히 파이썬스러운 답이 있는 데, 여러 대안중 가장 맘에 드는 것은
$ ./manage.py shell
...
>>> exec(open('myscript.py').read())
이다.

(엑셀도감) 참조하는 넘, 참조당하는 넘 오피스/VBA/Office.JS

엑셀 사용하면서 수식을 사용하지 않는 사람은 없는 데, 수식에 걸어둔 셀로 이동하거나 본인을 참조한 셀로 이동하는 단축키이다.
그러나 수식에서 참조하는 모든 셀로 이동하는 것은 아닌 듯, 첫 셀이나 셀 영역으로 이동한다.

내침 김에 한글 팁 하나 더 오피스/VBA/Office.JS

오피스를 많이 사용하다가 한글을 사용하려니 불편한 점이 몇 가지 있어 비슷한 기능을 찾아 보게 된다. 이번에는 표안의 값을 수식으로 자동계산되는 기능이다. 워드에도 비슷한 기능이 있는 걸로 기억하는 데, 한글은 이 기능을 [블록 계산식]이라고 한다.

위와 같은 표에서 [매각소유일수]는 보유한 주식을 연속으로 처분하는 데 필요한 시간을 의미한다. 20일간의 평균거래량으로 보유한 주식수를 나눈 값이다. 사실 이런 예상치가 실제와는 큰 차이가 있을 걸로 보이는데, 그 얘기는 주제에 벗어나므로 여기까지만...

엑셀처럼 A,B,C 등 알파벳으로 컬럼을 표시하고 1,2,3 등 숫자로 행을 표시한다. 그래서 표의 최상단 왼쪽 셀은 A1이다. 그리고 같은 행의 오른쪽 컬럼은 B1, C1 등으로 표시하여 수식을 표현할 수 있다. 이런 주소 표현은 엑셀의 절대주소 표시방식과 비슷하다. 상대적인 주소 표현은 [쉬운 범위] 드랍다운박스에서 고를 수 있다. [함수]드랍다운 박스에서는 여러 함수가 있는 데, 이 정도의 함수지원이면 충분해 보인다.




1 2 3 4 5 6 7 8 9 10 다음