PROGRAMMING WORKSHOP

프로젝트기성관리 |

지난페이지에서 자동으로 콘트롤이 만들어지던 것을 디자인타임에 그려 넣는 것으로
바꾸었다, 좀더 이해하시기 편한 상태가 된 셈이다
UserForm을 잘 사용하면 여러분이 만드는 소루션의 가치가 높아지는 것이니
흥미를 갖고 계속 기능을 추가하면서 UserForm에 능숙하여 보도록 하자

기성양식을 추가하는 기능이 있으면 삭제하는 기능도 있어야 하는 것은 상식이다
삭제 버튼을 하나 추가하자
이때 잊지 말아야 할 순서는 버튼을 그려 넣고
반드시 속성창에 의미있는 이름을 지어주고
버튼의 캡션에 사용할 문자열을 상수로 만들어 놓고
물론 이것을 디자인속성창에서 캡션을 주어도 좋지만, 이름짓는 것을 제외하고는
모두 폼이 초기화될때 프로그래밍적으로 처리하는 것이 편리하고 통제하기 쉬워진다
그래서 상수를 아래와 같이 추가하여 지어주고


Const TAB_PAGE_1_CAPTION As String = "기성물량편집"
Const TAB_PAGE_2_CAPTION As String = "서식편집"
Const TAB_PAGE_3_CAPTION As String = "기성문서편집"
Const BTN_ADD_REPORT_CAPTION As String = "기성추가"
Const BTN_VIEW_ALL_REPORT_CAPTION As String = "전체보기"
Const BTN_DEL_REPORT_CAPTION As String = "기성삭제"

그리고 UserForm의 로딩초기화에서

Me.cmdReportDelete.Caption = BTN_DEL_REPORT_CAPTION
Me.cmdReportDelete.Enabled = False

Enabled 속성은 False로 해주고
그리고 삭제의 조건이 될때만 Enabled=True로 실행중에 조치해준다
삭제의 조건이 되는 것은 
보고서목록에서 아래의 그림과 같이 최근기성양식만 삭제하도록 한다
이것은 목록상자의 Change이벤트에서 아래의 한줄을 추가한다

Sub ListBox_Change()
...
...
...
Me.cmdReportDelete.Enabled = isLastReportSelected(oLstCom)
End Sub

아래와 같이 함수하나 만들어서..

Function isLastReportSelected(oX As MSForms.ListBox)
If oX.ListCount = 0 Then Exit Function
If oX.ListIndex = oX.ListCount - 1 Then isLastReportSelected = True
End Function



뭐든지 삭제를 한다는 것은 중요한 일이다
그러니 정말 삭제할꺼냐...말꺼냐의 확인을 사용자에게서 받아야 할 것이다
그냥 덜렁메시지 박스하나만 보여서는 성의가 없다
기성양식추가 폼을 삭제에서도 활용하도록 하는 것이 좋은 방법일 것이다
그렇다면 기성약식추가할때 추가확인 목록을 작성하는 것을 그대로 활용하면 되는 셈이다

그런용도로 frmReportDatail폼을 사용하려면 전역변수를 하나 만들어서
이 변수의 값을 [삭제]를 할 것인지 [추가]를 할 것인지를 표시하는 용도로 사용하면 좋을 것이다

Public sDetailType As String

그러면 frmReportDeatil폼이 로딩되면서 이 값을 읽고 폼의 구성을 조금 달리하도록 하면 된다



무엇이던지 삭제를 하면 그냥 삭제만 한다는 생각으로 끝나면 안된다
삭제후 목록상자에 남아있는 삭제된 기성보고서목록도
삭제된 상태로 동기화를 시켜주어야 할 것이고
삭제후 시트의 상태는 어떤 상태로 유지하게 하여야 할 것인지도 고려하여야 할것이다
삭제를 하던, 추가를 하던 정보의 상태의 변화에 따른 관련된 콘트롤이던
정보의 변수이던 모두 동기화혹은 초기화를 하여 주어야 한다는 점
단순히 삭제는 그냥 Delete하나 하면 끝나지만
관련된 준비작업과 작업후 뒷정리를 잘 하여주어야 한다는 점을 잊지 말아야 한다
그리고 외부에서 UserForm의 콘트롤이나 함수혹은 프로시져를 참조하여야 하는
일이 생기게 된다
이때 UserForm내부의 함수나 프로시져들은 Private 로 선언되어 있다
이것을 Public 으로 바꿔저야 외부에서 해당 폼의 자원에 접근할수 있다


'Private Sub fillListBox_completion_nums(oList As MSForms.ListBox)
Public Sub fillListBox_completion_nums(oList As MSForms.ListBox)
Dim oCol As Collection, varX As Variant
oList.Clear
Set oCol = modMain.getCompletionNumbers
If oCol.Count = 0 Then
Else
    For Each varX In oCol
        oList.AddItem varX
    Next
End If
End Sub

삭제 같은 것은 그냥 시트상에서 마우스로 선택하여 삭제 하여도 될 것이나..
UserForm의 활용의 학습을 위하여 많은 것을 해보여 드리고자 하는 것이니
오버디자인 한다 싶어도 흥미있게 보시면서
아하..이 부분은 이런 곳에 활용하면 되겠구나..하는 영감을 얻고
활용하시라는 의미가 크다는 점을 아시고 학습하시기를 권한다

***[LOG-IN]***

기성물량을 입력하는 것을 시트상에서 입력을 하여도 좋겠지만
입력도구를 한번 추가 시켜 보도록 하자
아래의 그림과 같이 라벨콘트롤,텍스트박스콘트롤,스핀버튼콘트롤
그리고 명령 버튼을 하나씩 추가 하자



이 콘트롤들은 조건이 맞을때만 활성화되고 조건이 맞지 않을때는
비활성화시켜주는 것이 사용자가 쓸데없이 콘트롤을 크릭하고 하는 것을
방지 할수 있을것이고, 시각적으로 물량편집을 할수 있는 상황이라는 것을
알려 주는 역활이 될 것이다
그룹상자로 여러개의 컨트롤을 하나로 묶어도 좋겠지만,화면이 좁아서
그냥 각각 다루도록 하자
그대신 프로시져를 만들어서 여러개의 콘트롤을 처리하게 한다
아래와 같이 만들고 폼이 로딩할때는 setInsertTool False 로 하면
모든 콘트롤이 비활성화되지만, 실행하면서 기성과 품목을 선택할때
setInsertTool True로 호출하면 각 콘트롤들이 활성화되어 정보를
입력할수 있는 상황이 될수 있을 것이다

Sub setInsertTool(bX As Boolean)
Me.cmdInsert.Enabled = bX
Me.txtInsert.Enabled = bX
Me.lblCurrentStatus.Enabled = bX
Me.SpinButton1.Enabled = bX
Me.txtInsert.Text = ""
If bX Then
    Me.lblCurrentStatus.Caption = Me.lstTaskNames.List(Me.lstTaskNames.ListIndex, 1) & vbNewLine & _
                                                "총물량: " & Me.lstTaskNames.List(Me.lstTaskNames.ListIndex, 2)
Else
    Me.lblCurrentStatus.Caption = ""
End If
End Sub

아래의 그림과 같이 어떤 기성의 어떤 품목을 선택하였을때 교차되는 셀에
값을 넣을수 있는 조건이 되면 활성화시킨다



그리고 버튼을 크릭하면 해당 셀에 값이 입력되게 하는 것이 편리할지 어떨지는
각자 해보시면서 ,아무튼 학습을 겸한 것이니까, 많은 가능성을 보시면서 하면 될 것이다