Orang beriman memiliki derajat yang tinggi disisi Tuhan, tetapi derajatnya masih kalah tinggi dengan orang yang beriman lagi berilmu
Pada pembahasan tentang prosedur diseri pertama telah dibahas tentang prosedur dan deklarasinya, termasuk dalam hal penggunaan argumen didalam prosedur. Pembahasan kali ini akan diawali dengan pemanfaatan variabel dalam menyuplai nilai-nilai argumen dalam pemanggilan prosedur. Prosedur function akan dibahas selanjutnya. Setelah itu akan dibahas tentang ByVal dan ByRef dalam beberapa contoh prosedur. Kali ini pembahasan akan menggunakan file BelajarVBA005.xlsm yang dapat diunduh disini.
Memanfaatkan variabel untuk menyuplai prosedur berargumen
Penggunaan variabel dalam pemanggilan prosedur berargumen lebih banyak terjadi dibandingkan penggunaan nilai tetap. Penggunaan variabel akan memberikan manfaat penggunaan prosedur berargumen yang jauh lebih banyak.Misal di general module mod05 ada sebuah prosedur sub berargumen yang bertugas untuk menampilkan suatu output. Anggap saja proses yang ada dalam prosedur ini cukup panjang karena ada suatu proses yang bertugas untuk memilih template output yang akan ditampilkan, tetapi diwakili oleh sebaris kode program untuk menampilkan pesan dengan MsgBox :
Public Sub TampilkanPesan(sPesan As String)
MsgBox "Pesan : " & sPesan
End Sub
Jadi, ceritanya, seluruh output bisa dibentuk melalui prosedur bernama TampilkanPesan, selama prosedur ini mendapatkan suplai input data yang baik. Dengan demikian, prosedur TampilkanPesan dapat digunakan oleh banyak proses selama proses tersebut dapat menyediakan nilai input data kedalam argumen yang dimiliki oleh prosedur TampilkanPesan.
Agar prosedur TampilkanPesan bisa mendapatkan suplai nilai data yang sesuai, maka dibuatlah sebuah prosedur yang bertugas untuk menyusun data yang akan disuplai ke TampilkanPesan. Prosedur menyusun data tersebut adalah sebagai berikut :
Public Sub PenyusunPesan( _
Optional sData As String = "- tidak ada pesan -")
TampilkanPesan "[via prosedur penyusun pesan]" & _
vbCrLf & sData
End Sub
Anggap saja ada sebuah proses yang menerima inputan dari user berupa penekanan tombol dan sebagainya. Untuk contoh, proses tersebut diwakilkan dengan sebuah prosedur respon user sebagai berikut :
Public Sub PenyusunData()
Dim sNama As String
sNama = "Kid" 'data pertama
TampilkanPesan sNama 'proses langsung ke TampilkanPesan
PenyusunPesan sNama 'proses melalui PenyusunanData
sNama = vbNullString 'data kedua
TampilkanPesan sNama 'proses langsung ke TampilkanPesan
PenyusunPesan sNama 'proses melalui PenyusunanData
PenyusunPesan 'tanpa menyuplai nilai argumen
End Sub
Dari 3 (tiga) prosedur di atas, hanya prosedur PenyusunData yang bisa dijalankan melalui Run Macro di workbook window.
Di dalam prosedur PenyusunData ada 2 proses yang berbeda, yaitu :
- Proses pertama adalah proses pengiriman langsung nilai ke prosedur TampilkanPesan
- Proses kedua adalah proses pengiriman nilai ke prosedur PenyusunPesan dan prosedur PenyusunPesan yang akan menjalankan prosedur TampilkanPesan
Nilai variabel sNama yang akan dikirim ke proses (melalui 2 proses di atas) ada 2 buah yang dikirim satu per satu, yaitu :
- teks berbunyi 'Kid'
- teks kosong (NULLSTRING)
Jika prosedur PenyusunData dijalankan, maka akan tampak bahwa ada banyak proses yang bisa menggunakan sebuah prosedur berargumen. Dalam hal ini, yang dimaksud adalah prosedur TampilkanPesan. Prosedur TampilkanPesan dapat digunakan oleh prosedur PenyusunData secara langsung maupun digunakan oleh prosedur PenyusunPesan walaupun prosedur ini mendapatkan nilai argumen dari PenyusunData.
Bisa jadi, awalnya yang terbentuk adalah proses menjalankan langsung prosedur TampilkanPesan secara langsung oleh PenyusunData. Dengan berkembangnya waktu dan kebutuhan proses, maka dikembangkanlah suatu proses baru yang harus disisipkan diantara proses PenyusunData dengan proses TampilkanPesan. Maka dibentuklah prosedur PenyusunPesan. Kemudian prosedur PenyusunData mulai mengalihkan proses agar melalui prosedur PenyusunPesan lebih dulu.
Proses yang menggunakan nilai sNama adalah NULLSTRING memberikan tambahan informasi tentang pemanggilan prosedur berargumen yang berkaitan dengan argumen-argumen bersifat Optional. Pemanggilan prosedur dengan menyuplai nilai NULLSTRING untuk argumen Optional tidak sama dengan mengabaikan atau mengosongkan argumen. Hal ini dapat terlihat pada baris kode program berbunyi :
PenyusunPesan sNama 'proses melalui PenyusunanData
PenyusunPesan 'tanpa menyuplai nilai argumen
Ketika sNama berisi NULLSTRING, maka baris kode pemanggilan prosedur berbunyi PenyusunPesan sNama akan memperlakukan argumen sData milik prosedur PenyusunPesan mendapatkan suatu nilai tertentu, yang saat itu bernilai NULLSTRING. Sedangkan baris kode pemanggilan prosedur yang berbunyi PenyusunPesan, yaitu tanpa ada argumen yang diset untuk disuplai nilainya, akan membuat prosedur PenyusunPesan memperlakukan argumen sData tidak mendapat suplai nilai apapun. Hal inilah yang akan membuat prosedur PenyusunPesan akan menggunakan nilai default milik argumen sData, yaitu teks berbunyi '- tidak ada pesan -'.
Jadi, nilai default sebuah argumen akan digunakan jika argumen tersebut tidak mendapat suplai nilai input apapun dari pemanggil prosedur berargumen tersebut.
Prosedur jenis Function
Pembahasan selama ini kebanyakan menggunakan prosedur jenis Sub. Prosedur jenis function juga bisa berlaku layaknya prosedur jenis sub. Jadi, prosedur function tidak selalu harus berisi suatu proses menghitung sesuatu. Prosedur function yang bertipe public memang bisa digunakan dalam cell layaknya fungsi-fungsi bawaan Excel, tetapi dengan mengubahnya menjadi ber-scope level module, maka akan membuat prosedur function tersebut tidak akan bisa digunakan secara langsung melalui cell sebagai bagian dari fungsi-fungsi untuk formula.Seperti rangkaian prosedur function yang diletakkan dalam general module mod06 berikut ini, meski bisa digunakan dalam cell, Anda sepertinya tidak akan suka dengan efek hasil formulanya.
Public Function TampilPesan(sPesan As String) As Boolean
MsgBox "Pesan : " & sPesan
TampilPesan = True
End Function
Public Function SusunPesan( _
Optional sData As String = "- tidak ada pesan -") As Boolean
TampilPesan "[via prosedur penyusun pesan]" & _
vbCrLf & sData
SusunPesan = True
End Function
Public Function SusunData() As Boolean
Dim sNama As String
sNama = "Kid" 'data pertama
Call TampilPesan(sNama) 'proses langsung ke TampilkanPesan
Call PenyusunPesan(sNama) 'proses melalui PenyusunanData
sNama = vbNullString 'data kedua
Call TampilPesan(sNama) 'proses langsung ke TampilkanPesan
Call PenyusunPesan(sNama) 'proses melalui PenyusunanData
Call PenyusunPesan 'tanpa menyuplai nilai argumen
SusunData = True
End Function
Pada sebuah cell, misal di B1, bisa diberi formula : (boleh pilih salah satu atau letakkan pada cell yang berbeda-beda)
=TampilPesan(A1)
=SusunPesan(A1)
=SusunPesan(A1)
=SusunData()
Dengan mengubah seluruh scope Public menjadi Private, maka prosedur function yang ada tidak dapat digunakan lagi dalam cell. Cells yang berisi formula yang menggunakan prosedur function dengan keyword private akan menghasilkan error value #NAME?. Meski demikian, jika prosedur SusunData dijalankan melalui VBA, maka rangkaian prosedur function di atas akan berjalan dengan baik dan tampak sama dengan rangkaian prosedur yang ada diawal bahasan kali ini. Dari contoh tersebut, dapat disimpulkan bahwa tidak semua prosedur function yang dibuat harus diberi scope level dengan keyword public.
Salah satu keuntungan prosedur function adalah kemampuannya secara langsung memberikan nilai balik hasil suatu proses. Coba perhatikan prosedur-prosedur berikut ini :
Private Function CekValiditasInput(lNilai As Long) As Boolean
Dim lProses As Long
lProses = Abs(lNilai * 3)
CekValiditasInput = (lProses > 50)
End Function
Public Sub SebuahProsesPanjang()
Dim lNilaiInput As Long 'wadah nilai yang akan dicek
'contoh nilai input
'anggap saja nilai ini bisa berasal dari suatu proses tertentu
'anda bisa mencoba mengganti nilainya
'sebelum prosedur ini di-run
lNilaiInput = -10
'cek valid berdasar proses di prosedur function
'bernama cekvalidinput
If CekValiditasInput(lNilaiInput) Then
MsgBox "Valid" 'pesan ketika hasil cek adalah valid
Else
MsgBox "Tidak Valid" 'pesan ketika hasil cek adalah tidak valid
End If
End Sub
Ketika ada suatu proses yang membutuhkan suatu pemeriksaan validitas suatu nilai dengan menkanisme kalkulasi tertentu, maka prosedur function bisa digunakan sebagai prosedur yang bisa digunakan oleh berbagai proses. Contohnya adalah prosedur function CekValiditasInput yang menjadi alat cek validitas suatu nilai berdasar suatu proses berupa batas nilai positif dari lipat tiganya. Salah satu proses yang membutuhkan pengecekan adalah prosedur Sub bernama SebuahProsesPanjang. Dalam prosedur SebuahProsesPanjang ada baris kode untuk menyimpan suatu nilai yang harus diperiksa, yaitu yang berbunyi :
lNilaiInput = -10
Proses pengecekan berdasar metode kalkulasi yang ada dalam prosedur function CekValiditasInput adalah dengan menjalankan atau memanggil prosedur function pengeceknya, yaitu pada baris kode berbunyi :
If CekValiditasInput(lNilaiInput) Then
Saat proses mencapai baris kode ini, maka prosedur function CekValiditasInput akan dijalankan dengan nilai yang disuplai untuk argumen lNilai milik CekValiditasInput adalah yang tersimpan dalam variabel lNilaiInput milik prosedur sub SebuahProsesPanjang.
Di dalam prosedur CekValiditasInput akan terjadi suatu proses penyusunan nilai yang harus dicek, yang anggap saja seperti pada baris kode berbunyi :
lProses = Abs(lNilai * 3)
yang berupa pencarian nilai absolut dari nilai input parameter argumen lNilai dengan angka 3.
Kemudian hasil proses tersebut akan diperiksa terhadap suatu kriteria, yang anggap saja harus memenuhi kriteria lebih dari 50 seperti bagian berbunyi lProses > 50 pada baris kode berbunyi :
CekValiditasInput = (lProses > 50)
Hasil pengecekan oleh baris ini akan disimpan dalam nama prosedur function CekValiditasInput yang bisa menampung data ber-datatype Boolean menurut baris deklarasi prosedur function CekValiditasInput.
Jadi, sejatinya, baris kode berbunyi :
If CekValiditasInput(lNilaiInput) Then
adalah memeriksa nilai yang disimpan dalam nama prosedur function CekValiditasInput. Jika nilainya adalah TRUE, maka baris IF tersebut akan setara dengan bunyi baris kode berikut :
If TRUE Then
dan ketika yang disimpan nama prosedur function CekValiditasInput adalah nilai FALSE, maka akan setara dengan kode berbunyi :
If FALSE Then
Jadi, dengan penggunaan prosedur function seperti CekValiditasInput, proses yang panjang dan dapat dipakai oleh prosedur lain (dalam hal ini selain prosedur sub SebuahProsesPanjang) akan memberi keuntungan antara lain berupa :
- kemudahan untuk fokus dalam menyusun alur proses cek menjadi lebih tepat sesuai kebutuhan
- kemudahan untuk memperbaiki proses cek
- kemudahan untuk mengembangkan metode pengecekan yang berkembang sesuai kebutuhan
- meringkaskan baris-baris kode program karena setiap prosedur proses tidak perlu berisi suatu proses cek yang berulang-ulang disetiap proses yang membutuhkan pengecekan
Memahami ByRef dan ByVal
Setelah mengenal prosedur Sub dan Function secara lebih baik, maka sebaiknya mengenal pula manfaat statement ByRef dan ByVal yang digunakan dalam deklarasi prosedur. ByRef dan ByVal digunakan pada bagian pendeklarasian prosedur disisi setiap argumen milik prosedur tersebut. ByRef dan ByVal sudah disinggung secara singkat pada pembahasan prosedur seri pertama. Kali ini akan dijabarkan lebih jauh pengaruh penggunaan ByRef dan ByVal. Default argumen dalam VB atau VBA adalah ByRef. Artinya, semua argumen yang tidak diberi pernyataan ByVal pastilah menggunakan ByRef.ByVal
ByVal adalah mengirimkan suatu nilai yang disuplai kedalam sebuah argumen dan kemudian si argumen menyalin nilai tersebut untuk dimanfaatkan. Jadi, yang digunakan oleh prosedur berargumen adalah sebuah salinan nilai saja. Karena ada proses penyalinan nilai, maka dibutuhkan ruang penyimpan nilai salinan tersebut, yang artinya akan terbentuk memori yang dikhususkan menyimpan salinan nilai tersebut. Proses menyalin ini tetap saja membutuhkan waktu walaupun sangat cepat. Contohnya adalah rangkaian prosedur yang diletakkan dalam general module bernama mod08 berikut ini :'Kisah ByVal
'Pemeran Utama : Otong dan Yani
'statement ByVal dalam deklarasi harus ditulis
Public Sub Otong(ByVal lKertasSiOtong As Long)
lKertasSiOtong = 7
End Sub
Prosedur bernama Otong memiliki argumen bernama lKertasSiOtong yang diatur untuk menerima suplai suatu nilai ber-datatype Long dengan cara pengiriman nilai parameter argumen sebagai ByVal alias sebuah salinan nilai yang disuplaikan. Kemudian, prosedur bernama Yani akan memanfaatkan prosedur Otong tadi. Prosedur bernama Yani adalah sebagai berikut :
Public Sub Yani()
Dim lAtmSiYani As Long
lAtmSiYani = 32 'mengisi sebuah nilai
Otong lAtmSiYani 'mengirim ke Otong
'menampilkan nilai dalam lAtmSiYani
'setelah dikirim ke Otong
'yang memiliki argumen lKertasSiOtong berkarakteristik ByVal
MsgBox "Nilai dalam lAtmSiYani : " & lAtmSiYani
End Sub
Ketika prosedur bernama Yani dijalankan, alur prosesnya adalah sebagai berikut :
- dipihak Yani
- variabel lAtmSiYani dibentuk dalam memori oleh baris kode :
- variabel lAtmSiYani diisi dengan nilai 32, yang sejatinya adalah menyimpan nilai 32 ke dalam memori, oleh baris kode :
- Yani memanggil Otong dengan memberikan nilai dalam lAtmSiYani
- Otong menyalin nilai tersbut kedalam argumen lKertasSiOtong karena menggunakan ByVal
- dipihak Otong
- argumen lKertasSiOtong saat ini sudah berisi salinan nilai dari lAtmSiYani
- nilai dalam memori lKertasSiOtong saat ini masih bernilai 32
- Otong mengubah nilai dalam lKertasSiOtong menjadi 7 oleh baris kode :
- sampai disini, memori yang dimiliki lKertasSiOtong sudah berganti dari 32 menjadi 7
- proses dipihak Otong selesai
- proses kembali kepihak Yani
- saat ini, memori yang dimiliki lAtmSiYani tetaplah 32, meskipun tadi sudah diserahkan kepada lKertasSiOtong milik Otong karena Otong hanya menyalinnya kedalam lKertasSiOtong
- Pengubahan lKertasSiOtong milik si Otong tidak mempengaruhi nilai dalam lAtmSiYani
- Kemudian Yani menampilkan isi lAtmSiYani pada baris kode :
- Dan si Yani mendapati bahwa lAtmSiYani masih bernilai 32.
ByRef
ByRef adalah mengirimkan lokasi memori suatu nilai yang disuplai kedalam sebuah argumen. Jadi, yang digunakan oleh prosedur berargumen bukanlah nilai yang ada dimemori, tetapi blok memori penyimpan data tersebut secara langsung. Akibatnya, pengubahan nilai pada variabel argumen akan membuat berubahnya nilai yang disimpan dalam memori. Akhirnya, prosedur yang memanggil prosedur berargumen tersebut akan mendapati bahwa nilai yang disuplainya telah berubah. Contohnya adalah rangkaian prosedur yang diletakkan dalam general module bernama mod08 berikut ini :'Kisah ByRef
'Pemeran Utama : Agus dan Galuh
'deklarasi prosedur berikut ini bisa juga ditulis dengan
'Public Sub Agus(lDompetSiAgus As Long)
Public Sub Agus(ByRef lDompetSiAgus As Long)
lDompetSiAgus = 5
End Sub
Prosedur bernama Agus memiliki argumen bernama lDompetSiAgus yang diatur untuk menerima suplai suatu nilai ber-datatype Long dengan cara pengiriman nilai parameter argumen sebagai ByRef alias lokasi memori si nilai yang disuplai. Kemudian, prosedur bernama Galuh akan memanfaatkan prosedur Agus tadi. Prosedur bernama Galuh adalah sebagai berikut :
Public Sub Galuh()
Dim lRekeningSiGaluh As Long
lRekeningSiGaluh = 12 'mengisi sebuah nilai
Agus lRekeningSiGaluh 'mengirim ke Agus
'menampilkan nilai dalam lRekeningSiGaluh
'setelah dikirim ke Agus
'yang memiliki argumen lDompetSiAgus berkarakteristik ByRef
MsgBox "Nilai dalam lRekeningSiGaluh : " & lRekeningSiGaluh
End Sub
Ketika prosedur Galuh dijalankan, alur prosesnya adalah sebagai berikut :
dipihak Galuh
- variabel lRekeningSiGaluh dibentuk dalam memori oleh baris kode :
- variabel lRekeningSiGaluh diisi dengan nilai 12, yang sejatinya adalah menyimpan nilai 12 ke dalam memori, oleh baris kode :
- Galuh memanggil Agus dengan memberikan lRekeningSiGaluh karena argumen lDompetSiAgus milik Agus menggunakan ByRef
- dipihak Agus (sepertinya si Agus tertawa bahagia dapat rekeningnya Galuh)
- argumen lDompetSiAgus saat ini sudah berisi memori yang dimiliki oleh lRekeningSiGaluh
- nilai dalam memori saat ini masih bernilai 12
- Agus mengubah nilai dalam lDompetSiAgus menjadi 5 oleh baris kode :
- sampai disini, memori yang dimiliki lDompetSiAgus sudah berganti dari 12 menjadi 5
- proses dipihak Agus selesai
- proses kembali kepihak Galuh
- saat ini, memori yang dimiliki lRekeningSiGaluh yang tadi sudah diserahkan kepada lDompetSiAgus milik Agus sudah diubah oleh Agus menjadi bernilai 5.
- Kemudian Galuh menampilkan isi lRekeningSiGaluh pada baris kode :
- Dan si Galuh mendapati bahwa lRekeningSiGaluh yang tadinya berisi 12 sudah berubah menjadi 5.
- Siapa akhirnya yang tertawa bahagia dan siapa yang akhirnya bersedih ?
Pemanfaatan ByRef dan ByVal
Pada pembangunan suatu aplikasi, ByRef dan ByVal akan memberikan banyak kemudahan dalam mentransfer suatu nilai dari satu proses ke proses lain. Hal ini akan membuat alur proses bisa menjadi lebih efisien. Contohnya adalah seperti rangkaian prosedur yang diletakkan pada general module bernama mod09 berikut :- Prosedur Function TotalDiscount berisi proses penghitungan yang nilai baliknya adalah nilai discount.
ByVal curDisc As Currency _
, ByVal curJual As Currency _
, curNetJual As Currency _
) As Currency
'anggap saja proses komputasinya
'sangat rumit dan panjang
TotalDiscount = curDisc * curJual
curNetJual = curJual - TotalDiscount
End Function
- Prosedur Sub Perhitungan adalah prosedur yang membutuhkan kerja kalkulasi discount sekaligus dengan profit.
Dim curSales As Currency
Dim curDiscount As Currency
Dim curProfit As Currency
'nilai awal
curSales = 1000 'nilai jual
curDiscount = 0.17 'discount 17%
'proses komputasi yang rumit
curDiscount = TotalDiscount(curDiscount, curSales, curProfit)
'hasil akhir
MsgBox "Nilai jual = " & curSales & vbCrLf & _
"Discount = " & curDiscount & vbCrLf & _
"Profit = " & curProfit
End Sub
Alur proses ketika prosedur Perhitungan dijalankan adalah :
- dipihak Perhitungan
- terbentuk memori untuk curSales, curDiscount, dan curProfit melalui baris-baris deklarasi :
Dim curDiscount As Currency
Dim curProfit As Currency
- Nilai penjualan disimpan dalam curSales dan persentase discount disimpan dalam curDiscount pada baris-baris kode :
curDiscount = 0.17
- sampai disini, curProfit belum diisi apapun
- proses kalkulasi untuk mendapatkan nilai discount beserta profitnya adalah dengan menggunakan prosedur function TotalDiscount
- prosedur function TotalDiscount akan memberikan nilai balik berupa total discount yang akan disimpan dalam curDiscount
- prosedur function TotalDiscount juga akan menghasilkan nilai profit yang disimpan dalam argumen curNetJual milik TotalDiscount
- proses pemanggilan TotalDiscount adalah pada baris kode :
- dipihak TotalDiscount
- prosedur TotalDiscount menyalin nilai persentase discount dari curDiscount milik Perhitungan kedalam argumen curDisc milik TotalDiscount karena menggunakan karakteristik ByVal.
- prosedur TotalDiscount juga menyalin nilai penjualan dari curSales milik Perhitungan kedalam argumen curJual milik TotalDiscount karena menggunakan karakteristik ByVal.
- prosedur TotalDiscount mendapatkan memori curProfit milik Perhitungan yang diserahkan kepada argumen curNetJual milik TotalDiscount karena menggunakan karakteristik ByRef.
- nama function akan menyimpan nilai discount saat memproses baris kode :
- Profit dihitung dan hasilnya disimpan ke lokasi memori curNetJual melalui baris kode :
- pihak function TotalDiscount selesai dan proses kembali ke prosedur Perhitungan
- dipihak Perhitungan
- variabel curDiscount sudah berisi nilai discount yang didapat dari nilai balik function TotalDiscount
- variabel curProfit mendapatkan nilai profit dari function TotalDiscount karena argumen curNetJual yang menggunakan ByRef telah berubah nilainya.
- kemudian, nilai-nilai dalam variabel curSales, curDiscount, dan curProfit ditampilkan menggunakan kotak pesan melalui baris kode :
"Discount = " & curDiscount & vbCrLf & _
"Profit = " & curProfit
Dari contoh diatas memberi gambaran sederhana tentang penggunaan ByRef dan ByVal yang dapat membuat sebuah prosedur menghasilkan banyak nilai yang bisa disimpan dan ditransfer ke prosedur lain atau dikembalikan ke prosedur pemanggilnya.
Insya Allah pembahasan berikutnya adalah tentang pengenalan penggunaan prosedur jenis property dalam sebuah general module. Juga akan dibahas padanan penggunaan prosedur function dan sub untuk menggantikan penggunaan prosedur jenis property. Bahasan penutup tentang prosedur nantinya adalah gambaran umum untuk menentukan proses yang sebaiknya disusun sebagai sebuah prosedur yang bisa digunakan berulang-ulang.
No comments:
Post a Comment