[프로그램 구현]
Option Explicit
Sub 구구단()
Dim i As Integer, j As Integer 'i는 구구단 앞 숫자, j는 구구단 뒷 숫자
Dim iRow As Integer, iCol As Integer, iLastCol '셀 주소 행, 열, 마지막 열
Dim iLastDan As Variant, iDisplayDan As Variant '구구단 최종 단수, 한 줄에 표시할 단수. 취소 버튼이 있기 때문에 Variant로 줘야 합니다.
Application.ScreenUpdating = False '처리하는 동안 화면 갱신하지 않음
' 문장 2개를 나란히 쓸 때는 콜론으로 연결
iRow = 3: iCol = 1
Do
iLastDan = Application.InputBox("몇 단까지 작성할까요?", Title:="최종 단수", Default:=9, Type:=1) '기본 값 9, 숫자가 아닌 값 입력시 에러 발생
If iLastDan <> False Then '취소 버튼 값을 false임
Exit Do
End If
Loop ' 계속 반복해야 하므로 until 또는 while을 쓸 필요가 없으며, if 문에서 exit do 처리함
Do
iDisplayDan = Application.InputBox("한 줄에 표시할 단수는 몇 개입니까?", Title:="표시할 단수", Default:=4, Type:=1)
If iDisplayDan <> False Then
Exit Do
End If
Loop
Cells.Delete '전체셀 삭제, 초기화
For i = 2 To iLastDan '최종 단수까지 실행
Range(Cells(iRow, iCol), Cells(iRow, iCol + 4)).Merge '5개 열 병합
With Cells(iRow, iCol)
.Formula = i & " 단"
.HorizontalAlignment = xlCenter '수평 가운데 정렬
.Font.Bold = True '글자 굵게
End With
For j = 1 To 9 '해당 구구단 1부터 9까지 처리
Cells(iRow + j, iCol) = i
Cells(iRow + j, iCol + 1) = "*"
Cells(iRow + j, iCol + 1).HorizontalAlignment = xlCenter
Cells(iRow + j, iCol + 2) = j
Cells(iRow + j, iCol + 3) = "="
Cells(iRow + j, iCol + 3).HorizontalAlignment = xlCenter
Cells(iRow + j, iCol + 4).Formula = "=" & Cells(iRow + j, iCol).Address(0, 0) & "*" & Cells(iRow + j, iCol + 2).Address(0, 0) '셀 주소를 이용하여 수식 입력, $표시 제거
Next
If i Mod iDisplayDan = 1 Then '표시할 단수가 되면
iRow = iRow + 11 '표시할 행수를 11줄 내려 감
iCol = 1 '표시할 열을 1, 다시 말해 A열로 함
Else
iCol = iCol + 6 '표시할 열을 6개 오른쪽으로 이동함
End If
Next
Range("a1") = "구 구 단"
iLastCol = iDisplayDan * 6 - 1
Range(Cells(1, 1), Cells(1, iLastCol)).Merge 'A1부터 1행 마지막 열까지 셀 병합
Range("a1").Select
With Selection
.HorizontalAlignment = xlCenter
.Font.Size = 16
.Font.Bold = True
End With
For i = 6 To iLastCol Step 6 '6개 열마다 열 너비를 5로 함
Columns(i).ColumnWidth = 5
Next
Cells.EntireColumn.AutoFit '전체 셀의 열 너비 자동 맞춤
Cells.NumberFormat = "#,##0"
Application.ScreenUpdating = True '화면 갱신 복원
End Sub
1. 변수 선언 및 값 대입
Dim i As Integer, j As Integer 'i는 구구단 앞 숫자, j는 구구단 뒷 숫자
Dim iRow As Integer, iCol As Integer '시작 행, 시작 열
iRow = 3
iCol = 1
i, j, iRow, iCol 변수를 지정하고, 타입을 정수형식으로 지정했습니다. VBA에서 변수 타입은 변수마다 지정해야지 dim i,j as integer 라고 변수를 선언하면 j는 정수타입이지만, i는 variant(가변데이터) 변수가 됩니다.
iRow란 변수에 3, iCol 변수에 1을 대입했는데,
2단을 표시할 행이 3행이므로 3을 준 것이고, 2단의 시작이 A열이므로 1이라고 값을 지정한 것입니다.
2. 모든 셀 삭제
Cells.Delete
3. '구 구 단' 이라는 제목 입력
Range("a1").formula = "구 구 단"
Range(Cells(1, 1), Cells(1, 23)).merge
Range("a1").Select
With Selection
.HorizontalAlignment = xlcenter
.Font.Size = 16
.Font.Bold = True
End With
① a1셀에 '구 구 단'이라고 입력합니다. range("a1")="구 구 단"이라고 해도 됩니다.
문자는 "(큰 따옴표)로 둘러 싸야 하며, '(작은 따옴표)를 사용하면 에러가 납니다.
② a1셀에서 w1셀까지 연속된 범위를 셀 병합하라는 명령입니다.
③ a1셀을 선택하라는 명령입니다.
④ selection이란 선택된 셀이란 의미로 여기서는 a1셀이 되며, seletion을 공통인수로 사용한다는 의미입니다.
⑤ 수평 정렬의 속성 값이 가운데 이므로 가운데 정렬이 됩니다.
⑥ 폰트 크기의 속성 값이 16이므로 폰트 크기가 16으로 변경됩니다.
⑦ 폰트 굵게의 속성 값이 참이므로 폰트가 굵게 변경됩니다.
⑧ with 문을 끝냅니다.
4. 구구단 내용 기록
For i = 2 To 9
Range(Cells(iRow, iCol), Cells(iRow, iCol + 4)).merge
Cells(iRow, iCol) = i & " 단"
Cells(iRow, iCol).HorizontalAlignment = xlcenter
Cells(iRow, iCol).Font.Bold = True
For j = 1 To 9
Cells(iRow + j, iCol) = i
Cells(iRow + j, iCol + 1) = "*"
Cells(iRow + j, iCol + 1).HorizontalAlignment = xlcenter
Cells(iRow + j, iCol + 2) = j
Cells(iRow + j, iCol + 3) = "="
Cells(iRow + j, iCol + 3).HorizontalAlignment = xlcenter
Cells(iRow + j, iCol + 4).formula = "=" & i & "*" & j
Next
If i Mod 4 = 1 Then
iRow = iRow + 11
iCol = 1
Else
iCol = iCol + 6
End If
Next
① 구문 분석
for i = 2 to 9
실행문 1
for j = 1 to 9
실행문2
next
if i Mod 4 = 1 then
실행문3
else
실행문4
end if
next
for ~ next문 안에 for ~ next문과 if문이 들어 있습니다.
② i는 2단부터 9단까지의 단수를 담은 변수이며, j는 1부터 9까지 단수별로 곱할 값을 담은 변수입니다.
for i 문 안에 for j 문이 들어 있으므로, i=2인 동안 j가 1에서 9로 변하고, j가 9까지 모두 실행되면 i가 3이 됩니다. 다시 j가 9까지 모두 실행되면 i가 4가 됩니다. 이런 식으로 for문을 중첩해서 2단부터 9단까지 구구단의 숫자를 차례대로 입력할 수 있는 것입니다.
③ 셀 병합, 가운데 정렬, 글자 굵게
Range(Cells(iRow, iCol), Cells(iRow, iCol + 4)).merge
Cells(iRow, iCol) = i & " 단"
Cells(iRow, iCol).HorizontalAlignment = xlcenter
Cells(iRow, iCol).Font.Bold = True
i가 2일 때 iRow는 3, iCol이 1이므로 cells(iRow, iCol)은 A3셀이 되며, Cells(iRow, iCol + 4)은 A3셀에서 4칸 옆으로 이동하므로 E3셀이 됩니다. 따라서, Range(Cells(iRow, iCol), Cells(iRow, iCol + 4)).merge 란 A3셀에서 E3셀까지를 병합하라는 명령입니다.
만약 i가 3이 되면 if문 내 iCol = iCol + 6 수식에 따라 iCol값이 7이 되고, iRow는 변함이 없으므로, cells(iRow, iCol)는 G3셀이 되고, Cells(iRow, iCol + 4)에서 iCol + 4 는 11이 되어 k열이 되므로 k3셀이 됩니다.
Cells(iRow, iCol) = i & " 단" 는 i가 2일 때 A3의 값은 "2 단"이라는 의미이므로 A3셀에 "2 단"이란 글자를 입력하라는 의미입니다. i가 3이 되면 iCol는 7, i는 3이므로 G3셀에 "3 단"을 입력하라는 의미입니다.
Cells(iRow, iCol).HorizontalAlignment = xlcenter
Cells(iRow, iCol).Font.Bold = True
A3셀, G3셀 등을 가운데 정렬하고 글씨를 굵게 하라는 것입니다.
Cells(iRow, iCol)가 반복되므로
with Cells(iRow, iCol)
.formula = i & " 단"
.HorizontalAlignment = xlcenter
.Font.Bold = True
end with
라고 해도 됩니다.
④ 해당 단의 구구단 표시
Cells(iRow + j, iCol) = i
Cells(iRow + j, iCol + 1) = "*"
Cells(iRow + j, iCol + 1).HorizontalAlignment = xlcenter
Cells(iRow + j, iCol + 2) = j
Cells(iRow + j, iCol + 3) = "="
Cells(iRow + j, iCol + 3).HorizontalAlignment = xlcenter
Cells(iRow + j, iCol + 4).formula = "=" & i & "*" & j
i, j가 2와 1일 때는
iRow가 3, iCol이 1이므로
Cells(iRow + j, iCol) = i 은
iRow+j는 4가 되므로,
A4셀의 값이 2라는 것이며,
Cells(iRow + j, iCol + 1) = "*"
Cells(iRow + j, iCol + 1).HorizontalAlignment = xlcenter
은 iCol+1이 2가 되므로
B4셀의 값이 * 라는 것이며,
수평으로 가운데 정렬하라는 의미입니다.
Cells(iRow + j, iCol + 2) = j
는 iCol+2가 3이 되므로
C4셀의 값이 1이 됩니다.
Cells(iRow + j, iCol + 3) = "="
Cells(iRow + j, iCol + 3).HorizontalAlignment = xlcenter
는 iCol+3이 4가 되므로
D4셀의 값이 '='이 되는 것이며,
수평으로 가운데 정렬하라는 의미입니다.
Cells(iRow + j, iCol + 4).formula = "=" & i & "*" & j
은 iCol+4가 5가 되므로
E4셀의 값의 수식이
=2*1 이 됩니다.
변수도 "(큰 따옴표)로 감싸면 변수가 아닌 문자가 됩니다. 다시 말해 i는 변수로서 값을 저장할 수 있지만, "i"는 변수가 아닌 단순한 문자 i 입니다. 따라서 "=i*j"하면 셀에 =i*j라는 문자가 입력됩니다.
그러므로, =2*1이 제대로 표시되도록 하려면 문자와 변수를 & 연산자로 연결해서 표현하여야 하며, "=" & i & "*" & j 가 됩니다.
수식으로 표현한다면
Cells(iRow + j, iCol + 4).formula = "=" & Cells(iRow + j, iCol).address(0,0) & "*" & Cells(iRow + j, iCol + 2).address(0,0)
이 됩니다.
.address를 붙이지 않으면 셀 주소의 값을 가져오므로, 주소를 가져오도록 .address를 추가한 것이며, address만 주면 절대참조형식으로 앞뒤에 $표시가 붙으므로, (0,0)을 추가해서 $를 제거한 상대 참조형식으로 표시되도록 했습니다.
j가 변하면 한 줄 아래 표시되고, 그에 따라 수식도 변하며, j가 10이 되어 i가 3이 되면 행은 같고, 6칸 오른쪽에 다음 단이 표시됩니다.
⑤ 6단이 될 경우와 단이 변할 경우 변수 값 변경
If i Mod 4 = 1 Then
iRow = iRow + 11
iCol = 1
Else
iCol = iCol + 6
End If
If i Mod 4 = 1 Then
iRow = iRow + 11
iCol = 1
Mod 연산자는 나머지를 구하는 연산자로서
"i를 4로 나눈 나머지인 단수가 1이라면"이란 조건은
다시 말해 5단일 경우란 의미입니다.
5단이 되면
iRow에 'iRow에 11을 더한 값'을 대입하라는 것이므로 iRow값은 14가 되고, iCol은 1로 만들어 A열로 바꾸는 것입니다.
이 때는 변수의 값만 달라지고,
실제 적용은 위로 올라가서 i가 6이 됐을 때 적용되므로
6단이 A14셀로 부터 시작하게 됩니다.
Else
iCol = iCol + 6
란 5단이 아니면 iCol 값을 'iCol+6'으로 바꾸므로 6칸씩 오른쪽으로 이동하면서 단을 기록하라는 의미가 됩니다.
⑥ 열 너비 지정 및 자동 맞춤
Range("f:f,l:l,r:r").ColumnWidth = 5
Cells.EntireColumn.AutoFit
F,L,R열의 너비를 5로 지정하므로, 열 너비가 5로 좁아지고,
전체 셀의 열 너비를 입력된 글자의 너비에 맞춰 자동 맟춤하라는 의미입니다.
[프로그램 확장]
구구단을 9단까지만 표시할 것이 아니라 99단 아니 999단까지도 표시할 수 있도록 단수를 입력받고, 한 번에 표시하는 단수가 현재 2~5단으로 4단인데 5단, 6단 등으로 바꿀 수 있도록 2가지 변수를 입력받는 것으로 프로그램을 변경해 보겠습니다.
변수를 입력 받는 메소드로 application.inputbox가 있으며,
변수명 = application.inputbox(prompt, title, default, type) 식으로 작성하는데,
prompt는 화면에 표시할 문장,
title은 창 이름,
default는 변수의 기본 값,
type은 문자인지(2), 숫자인지(1), 범위인지(8) 형식을 지정하는 것입니다.
application.inputbox 안에 입력할 인수는 순서대로 입력할 경우는 인수명을 기재할 필요가 없는데,
순서대로 입력하지 않을 경우는 인수명:=값 형식으로 '='이 아니라 ':='을 사용합니다.
예시)
iLastDan = Application.InputBox("몇 단까지 작성할까요?", Title:="최종 단수", Default:=9, Type:=1)
첫번째 인수명이 prompt이기 때문에 생략했으며, 두번째와 세번째 인수가 title과 default이므로 생략가능하나, 이해하기 쉽도록 표시했으며, type은 숫자이므로 1로 지정했습니다.
① 변수 추가
Dim iLastDan As Variant, iDisplayDan As Variant '구구단 최종 단수, 한 줄에 표시할 단수. 취소 버튼이 있기 때문에 Variant로 줘야 합니다. |
구구단 최종 단수와 한 줄에 표시할 단수를 입력받기 위해 iLastDan과 iDisplayDan 변수를 선언했고, 필요한 값은 숫자이지만, 취소 버튼이 있어 다른 값도 받아야 하기 때문에 변수 타입을 Variant로 지정했습니다.
② 최종 단수 입력 받기
Do
iLastDan = Application.InputBox("몇 단까지 작성할까요?", Title:="최종 단수", Default:=9, _
Type:=1)
If iLastDan <> False Then
Exit Do
End If
Loop ' 계속 반복해야 하므로 until 또는 while을 쓸 필요가 없으며, if 문에서 exit do 처리됨
위 프로그램을 실행하면 아래와 같은 화면이 나오는데, title은 최종 단수, prompt는 '몇 단까지 작성할까요?, default값은 9로 표시되고 있습니다.
iLastDan을 입력받는데, 취소 버튼을 누를 경우 반복할 수 있도록 do ~ loop 문 안에 아래 조건문을 넣었으며,
If iLastDan <> False Then
Exit Do
End If
취소 버튼 클릭시 false값이 반환되는데, false가 아닌 숫자일 때만 loop를 빠져 나올 수 있도록 하는 것입니다.
<> 는 비교연산자로 '같지 않다 또는 아니다'라는 의미이며, '같다'는 =을 사용하여 다른 언어에서는 ==을 사용하는 것과 다릅니다.
③ 한 줄에 표시할 단수 입력 받기
Do
iDisplayDan = Application.InputBox("한 줄에 표시할 단수는 몇 개입니까?", Title:="표시할 단수", _
Default:=4, Type:=1)
If iDisplayDan <> False Then
Exit Do
End If
Loop
변수가 iDisplayDan이라는 점 말고는 ②와 똑 같습니다.
④ for i 문 수정
For i = 2 To iLastDan |
표시할 단수를 무조건 2단에서 9단이 아니라 최종 단수까지 표시하도록 iLastDan으로 수정했습니다.
⑤ 한 줄에 표시할 단수 수식 수정
If i Mod iDisplayDan = 1 Then |
위에서는 무조건 4개씩 표현하도록 i Mod 4였는데, i Mod iDisplayDan으로 표시할 단수만큼 한 줄씩 표시하도록 수정했습니다.
⑥ 병합할 셀 범위 수정
Range(Cells(1, 1), Cells(1, iDisplayDan * 6 - 1)).Merge |
단과 단사이를 포함할 경우 한 단이 6열인데, 마지막 단은 5열이므로, 마지막 열은 iDisplayDan * 6 -1이 됩니다. 따라서 마지막 셀의 열을 iDisplayDan * 6 -1으로 수정한 것입니다.
다음에 또 iDisplayDan * 6 -1이 쓰이므로, iLastCol이란 변수를 선언(dim iLastCol as integer)한 다음
iLastCol = iDisplayDan * 6 -1
라고 쓰는 것이 이해하는데 더 편합니다.
⑦ 열 너비를 조절할 컬럼 표시방식 수정
For i = 6 To iLastCol Step 6
Columns(i).ColumnWidth = 5
Next
열 너비를 조절할 열이 F,L,R로 6의 배수인 6,12,18열이었는데, 단수에 따라 자동으로 6씩 증가하면서 열을 선택하도록 step을 6으로 줬고, i의 최대값을 마지막 열인 iLastCol 로 준 것입니다.
이렇게 하면 자유자재로 구구단을 만들 수 있습니다. 처음 단수는 2단으로 고정했는데, 이것도 변수를 하나 만들어 입력받으면 가능하지만 그럴 일은 거의 없을 듯하여 뺐습니다. 한 번 해보시고 싶은 분은 해보시기 바랍니다.
⑧ 천단위마다 콤마 표시
Cells.NumberFormat = "#,##0" |
천단위마다 콤마 표시를 하는 것이고, 0일 경우에도 0을 표시하라는 옵션입니다. 그런데, 구구단에 0이 올 수는 없으니 "#,###"으로 해도 됩니다.
⑨ 계산과정을 표시하지 않도록 설정
Application.ScreenUpdating = False 프로그램 Application.ScreenUpdating = True |
ScreenUdating이란 화면 갱신에 대한 속성으로 Application 개체 다음에 반드시 써야 하며, 갱신을 하지 않으면 false, 하면 true라고 표현합니다. 프로그램 처리과정에서는 갱신을 하지 않도록 false라고 주고, 끝 부분에 다시 원래값으로 돌아오도록 true라고 입력합니다.
'EXCEL - VBA' 카테고리의 다른 글
구구단 만들기(6) (엑셀 VBA 디버깅 2) (0) | 2022.12.15 |
---|---|
구구단 만들기(5) (엑셀 VBA 디버깅 1) (0) | 2022.12.14 |
구구단 만들기(3) (엑셀 VBA 프로그래밍 기초) (0) | 2022.12.12 |
구구단 만들기(2) (엑셀 VBA, 기록된 구구단 매크로 실행 및 분석) (0) | 2022.12.09 |
구구단 만들기(1) (엑셀 VBA의 매크로 기록하기) (0) | 2022.12.08 |