Saturday, July 27, 2013

BelajarVBA 006 - Object dalam Excel

Coretan Mr. Kid

Tuhan akan menganugerahi orang yang menjadikan setiap kesempatan sebagai sarana untuk mengingat Tuhan dengan sesuatu yang lebih baik dari pada sesuatu yang diminta oleh orang yang berdoa.

Excel VBA adalah sebuah bahasa pemrograman yang berorientasi object. Seluruh perangkat pemrograman dibentuk sebagai suatu object. Pembahasan kali ini adalah tentang object, terutama object-object utama dalam Excel seperti Workbook, Worksheet, dan Range.

Sebelum memulai pembahasan ini, coba bayangkan jika ada orang lain yang tanpa sepatah kata pun langsung masuk ke rumah Anda dan makan makanan yang ada di meja makan di rumah Anda. Tentu akan segera terasa bahwa ada sesuatu yang salah disana, seperti tidak pada tempatnya bagi si orang itu untuk menggunakan apa yang Anda miliki tanpa bertemu dulu dengan Anda.

Pada dasarnya, konsep object didalam pemrograman adalah seperti hal di atas. Ada diri Anda dan diri orang lain. Sama-sama manusia, tetapi memiliki nilai dan potensi yang berbeda. Ada rumah Anda dan bisa jadi si orang lain pun memiliki rumah yang bentuk, ukuran, warna, dan segala macam nilai detilnya berbeda dengan rumah Anda. Ada meja makan milik Anda yang diatasnya terhidang banyak makanan. Anda, orang lain, rumah Anda, rumah orang lain, meja makan Anda, makanan di atas meja makan Anda adalah sesuatu yang berwujud yang memiliki suatu nilai tertentu. Sesuatu yang berwujud itulah yang disebut object.

Konsep object dalam dunia nyata tersebut ditransformasikan ke dalam dunia pemrograman yang dikenal dengan Object Oriented Programming (OOP). Semua kegiatan dalam program akan berbasis interaksi antar object yang ada di dunia pemrograman, layaknya interaksi object diri Anda berinteraksi dengan object orang lain atau object diri Anda berinteraksi dengan object rumah Anda, dan sebagainya.

Setiap object memiliki potensi dan nilai-nilai tertentu yang menjadi pembentuk ciri khas si object tersebut.


Object

Sebuah benda yang berisi kumpulan data yang mencerminkan sesuatu dan kemampuan melakukan sesuatu atau merespon perlakuan terhadapnya sebagai satu kesatuan. Contohnya adalah sebuah workbook, worksheet, range, dan sebagainya. Object seperti Worksheet memiliki kumpulan data seperti nama worksheet, statusnya tersembunyi atau tidak, memiliki range, dan sebagainya. Worksheet memiliki kemampuan untuk melakukan sesuatu seperti mengkalkulasi, diaktifkan, memproteksi diri atau melepaskan proteksi diri, meng-copy data, mem-paste data dengan kondisi tertentu, dan sebagainya. Worksheet juga bisa merespon perlakuan terhadapnya seperti ketika ada range yang menjadi bagian dirinya berubah nilainya, ketika akan memulai proses kalkulasi, atau ketika diaktifkan, dan sebagainya.

Setiap object selalu memiliki elemen-elemen penyusun yang disebut member. Penyusunnya bisa berupa nilai-nilai atribut tertentu, object-object lainnya, prosedur-prosedur untuk melakukan sesuatu atau untuk menerima respon perlakuan terhadapnya. Member-member object tersebut dapat dikelompokkan menjadi 3 hal, yaitu :
  • Property : suatu data yang menjadi ciri khusus dirinya
  • Methods : prosedur-prosedur untuk melakukan sesuatu
  • Events : respon perlakuan user terhadap dirinya
Setiap member bisa diketahui dengan mudah termasuk kelompok yang mana berdasarkan icon yang ditampilkan VBE sebelum nama membernya. Contohnya seperti dalam gambar berikut ini :
Setiap object minimal memiliki salah satu dari macam-macam member tersebut. Misalnya, sebuah worksheet memiliki :
  • Property seperti Name, Range, Cells, AutoFilter, dan sebagainya.
  • Methods seperti Copy, PasteSpecial, Activate, Calculate, Evaluate, Move, PrintOut, dan sebagainya.
  • Events seperti Change, SelectionChange, Calculate, Activate, BeforeRightClick, dan sebagainya.

Collection

Wadah yang menampung minimal satu object yang sama. Contohnya adalah Worksheets yang menampung seluruh worksheet yang ada dalam sebuah workbook. Dengan demikian, sebuah collection juga object. Salah satu isi collection bisa dipilih untuk digunakan. Seperti memilih worksheet bernama 'Laporan' dari Worksheets, dimana Worksheets adalah sebuah Collection.


Beberapa object utama Excel

Excel memiliki beberapa object utama yang selalu ditemui, seperti :

Application

  • Berupa instansi aplikasi Excel.

Workbook dan Workbooks

  • Workbook adalah object yang lebih dikenal berisi minimal sebuah sheet.

  • Workbooks adalah kumpulan (collection) dari beberapa workbook. Keberadaan Workbooks dapat diketahui lebih jelas ketika membuka workbook lain dari workbook yang sedang aktif atau melalui menu File Open dalam workbook window. Pada VBA Project Explorer akan tampak beberapa VBProject milik workbook yang berbeda-beda.

Worksheet dan Chart

  • Worksheet adalah object yang lebih dikenal berisi range. Kumpulan worksheet adalah object collection bernama Worksheets.
  • Chart adalah object yang lebih dikenal berisi grafik. Kumpulan chart adalah object collection bernama Charts.
  • Kumpulan object yang berisi Worksheet atau Chart adalah object collection bernama Sheets.

Range

Object yang mewadahi cells dalam worksheet yang akan atau sedang digunakan. Worksheet berisi cells yang membentuk suatu datagrid. Setiap cell akan menjadi wadah nilai data. Cell memiliki posisi baris dan kolom relatif terhadap object yang berisi datagrid.

Gambar berikut ini adalah hal-hal dasar tentang cell.
  • Sebuah kotak datagrid disebut cell.
  • Lokasi kursor disebut ActiveCell dan pasti ada dalam satu buah cell.
  • Cells yang memiliki posisi baris yang sama dengan posisi kolom yang berbeda-beda disebut Rows.
  • Cells yang memiliki posisi baris yang berbeda-beda dengan posisi kolom yang sama disebut Columns.
Contoh untuk menjelaskan tentang makna cell adalah sebagai berikut :
  • Cell pertama dalam worksheet adalah cell di baris 1 dan kolom 1 dari worksheet. Alamatnya adalah A1.
  • Cell ketiga dalam worksheet adalah cell di baris 1 dan kolom 3 dari worksheet. Alamatnya adalah C1.
  • Cell di baris 2 dan kolom 5 dalam worksheet adalah pada alamat E2.
  • Ketika disebut ada suatu range C7:H8, maka cells yang akan digunakan (ada dalam range tersebut) adalah mulai dari cell worksheet di posisi baris 7 dan kolom 2 hingga baris 8 dan kolom 7.
  • Cell pertama pada range C7:H8 adalah cell pada baris 1 dan kolom 1 dalam range tersebut yang memiliki alamat referensi bernama C7.
  • Cell ketiga pada range C7:H8 adalah cell pada baris 1 dan kolom 3 dalam range tersebut yang memiliki alamat referensi bernama E7.
  • Cell di baris 2 dan kolom 5 dalam range C7:H8 adalah pada alamat referensi bernama G8.
  • ActiveCell ada di I4 meskipun sedang berkerja pada range C7:H8
Dari uraian diatas, secara umum bisa dikatakan bahwa range berisi cells beserta seluruh potensinya. Sedangkan cells adalah posisi suatu datagrid relatif terhadap object. Cells selalu menghasilkan range.


Cara menggunakan object

Object memiliki hirarki dari terluar sampai terdalam sesuai daftar member dan peta object tersebut. Setiap property atau methods dari object yang akan digunakan selalu diawali dengan menyebut nama object terluar yang berbeda sampai yang terdalam hingga tiba ke property atau methods yang akan digunakan. Penyebutan object tersebut dipisahkan dengan karakter titik. Secara umum syntax-nya adalah :
     object_terluar_yang_berbeda.object_member_1.dst.property_atau_methods

Misalnya untuk object range dalam Excel, ketika workbook dalam keadaan terbuka, bisa digunakan dengan syntax lengkap sebagai berikut :
Workbooks("nama workbooknya").Worksheets("nama worksheetnya").Range("alamat rangenya").property_atau_methods_nya

Contoh 1 : Menggunakan Workbook lain

Misalkan ada dua buah workbook yang terbuka, yaitu bernama Keuangan.xls dan Laporan.xls yang masing-masing berisi banyak worksheet. Ketika bekerja pada workbook Laporan.xls bisa menggunakan nilai yang ada dalam workbook Keuangan.xls pada sheet bernama Dataku di range dengan alamat B3 sampai G9. Proses ingin meng-copy nilai dalam range tersebut ke clipboard.

Proses ini jika dikerjakan manual oleh manusia adalah dengan urutan proses :
  • Ke workbook Keuangan.xls
  • Ke sheet bernama Dataku
  • Blok range B3 sampai G9
  • Klik kanan range yang telah di-blok dan pilih Copy
Penggunaan object-nya adalah sebagai berikut :
   Workbooks("Keuangan.xls").Worksheets("Dataku").Range("B3:G9").Copy

Artinya, dari workbook Laporan.xls, hubungi workbook bernama Keuangan.xls yang sedang terbuka. Kemudian ke worksheet bernama Dataku yang ada di workbook Keuangan.xls yang telah dihubungi tersebut. Di worksheet bernama Dataku tersebut, lakukan pemilihan cells agar didapat range mulai dari B3 sampai G9. Range yang dituju tersebut di-Copy ke clipboard.

Jadi, Copy adalah methods yang akan digunakan. Seluruh bunyi yang didepan kata Copy adalah cara memanggil object-nya. Object terluar yang berbeda dengan object yang sedang aktif bekerja adalah Workbooks("Keuangan.xls"). Hal ini disebabkan karena workbook lokasi kerja ada di workbook bernama Laporan.xls

Pada proses di atas, tidak ada proses pengaktifan object. Artinya, kita hanya memberi perintah tanpa harus beranjak ke tempat lain. Jadi kita tetap berada di activecell saat proses akan dimulai. Komputerlah yang sibuk berjalan kesana kemari menjalankan setiap proses yang kita perintahkan.

Contoh 2 : Menggunakan Worksheet yang berbeda dalam sebuah workbook

Contoh lainnya adalah pada workbook Laporan.xls yang memiliki tiga sheet, yaitu bernama Tampungan, Hasil, dan LembarKerja. Saat ini, sheet bernama LembarKerja sedang aktif. Jadi kursor atau activecell (lihat lagi tentang activecell pada pembahasan di atas) sedang berada di sheet LembarKerja.

Akan dilakukan proses Copy dari sheet bernama Tampungan pada range A2:J17 dan akan di-Paste Values ke sheet bernama Hasil pada range Z7. Proses Copy Paste ini akan memiliki proses secara manual atau yang bila dikerjakan manual oleh manusia adalah dengan urutan proses sebagai berikut :
  • Ke sheet bernama Tampungan
  • Blok range A2:J17
  • Klik kanan yang telah diblok dan pilih Copy
  • Ke sheet bernama Hasil
  • Blok range Z7
  • Klik kanan range Z7 yang telah diblok dan Pilih PasteSpecial
  • Kemudian pilih Values dan tekan tombol OK
Penggunaan object-nya adalah sebagai berikut :
   Worksheets("Tampungan").Range("A2:J17").Copy
   Worksheets("Hasil").Range("Z7").PasteSpecial xlPasteValues

Artinya, pada workbook yang sama, yaitu Laporan.xls (karena tidak ada proses pemanggilan object workbook), ke sheet Tampungan untuk memilih range A2:J17 yang dilanjutkan dengan meng-Copy ke clipboard. Kemudian ke sheet Hasil untuk memilih range Z7 yang dilanjutkan dengan melakukan PasteSpecial. Opsi yang dipilih dalam PasteSpecial adalah opsi xlPasteValues yang berarti mem-paste values-nya saja.

Object terluar yang berbeda dalam contoh ini adalah worksheet, yaitu harus ke worksheet Tumpangan sedangkan kita tetap berada di worksheet LembarKeja dan harus ke worksheet Hasil sedangkan kita masih saja tetap di worksheet LembarKerja.

Contoh 3 : Sheet aktif dan worksheet lain dalm workbook yang sama

Contoh lainnya lagi adalah ketika kita berada di sheet LembarKerja berikut ini. Proses akan meng-Copy nilai di range B3 yang ada di sheet Hasil ke sheet LembarKerja (tempat kita berada alias yang sedang aktif) di range C7.

Proses ini jika dilakukan oleh manusia bisa dengan alur proses berikut ini :
  • Ke sheet Hasil
  • Blok range B3
  • Klik kanan range B3 yang telah diblok lalu pilih Copy
  • [Ke sheet LembarKerja (tempat kita berada)]
  • Blok range C7
  • Klik kanan range C7 yang telah diblok dan pilih PasteSpecial
  • Kemudian pilih Values dan tekan tombol OK
Penggunaan object-nya adalah sebagai berikut :
   Worksheets("Hasil").Range("B3").Copy
   Range("C7").PasteSpecial xlPasteValues

Artinya, pada workbook yang sama dan saya tetap di sheet LembarKerja, ke sheet Hasil untuk memilih range B3 dan melakukan proses Copy ke clipboard. Kemudian kembali ke tempat saya yang dilanjutkan dengan memilih range C7 disertai proses PasteSpecial dengan opsi paste values-nya saja.

Pada contoh ini, saat ada di sheet LembarKerja dan membutuhkan sesuatu yang milik sheet Hasil, maka disertakan penyebutan nama object terluar yang berbeda, yaitu sheet bernama Hasil. Ketika akan melakukan paste ke range yang ada dalam sheet LembarKerja, tidak diperlukan lagi pemanggilan nama sheetnya sebagai object terluar yang berbeda. Hal ini disebabkan karena saat akan memproses terhadap sheet LembarKerja yang saat ini sedang aktif atau tempat kita berada, object terluar yang berbeda adalah range-nya. Oleh sebab itu range-nya disebut agar bisa memanfaatkan methods yang dimiliki si range tersebut.

:)

Proses yang memanfaatkan banyak object beserta seluruh potensinya seperti yang dicontohkan di atas akan menjadi hal yang sangat utama dalam Excel VBA. Hal-hal lebih lanjut tentang kegiatan seperti contoh akan dibahas lebih lanjut pada topik lain. Pembahasan selanjutnya masih akan berkaitan dengan object, yaitu tentang pengenalan property, methods, dan events dari suatu object. Khusus untuk events, akan difokuskan pada pengenalan events milik object Excel seperti Worksheets, Workbook, dan Application secara berurutan.



Friday, July 19, 2013

BelajarVBA 005 - Procedure seri 3

Coretan Mr. Kid

Kejujuran sering terkesan menghambat langkah usaha seseorang, padahal sesungguhnya saat itu kejujuran sedang membuka banyak pintu rezeki yang penuh berkah

Pembahasan kali ini adalah berkenalan dengan prosedur jenis property dan penggunaan prosedur jenis sub maupun function untuk bisa bekerja seperti prosedur jenis property. Pembahasan akan ditutup dengan gambaran dari penyusunan suatu proses yang dipecah menjadi banyak prosedur agar dapat meningkatkan daya guna sebuah prosedur dan memudahkan penyempurnaan suatu proses.



Property

Umumnya prosedur property digunakan dalam class module. Prosedur jenis property juga bisa digunakan general module (code module). Prosedur jenis properti mengatur ijin read (bisa digunakan) dan write (bisa diubah nilainya) dari sebuah properti. Prosedur property ada 3 jenis, yaitu Let, Set, dan Get. Property Let dan Set cenderung seperti prosedur Sub yang bertugas sebagai prosedur untuk menyimpan atau mengubah nilai suatu properti.

Keberadaan prosedur property Let dan Set menandai bahwa properti tersebut bisa diubah nilainya. Prosedur Get cenderung mirip dengan prosedur function yang bertugas sebagai prosedur untuk mengambil atau membaca nilai suatu properti. Keberadaan prosedur property Get menandai bahwa properti tersebut bisa digunakan atau dibaca nilainya. Contohnya seperti rangkaian script berikut :
  • misal di general module bernama mod10 diberi script :
     Private lMyNilai As Long    'variabel untuk property nilai
     Private rngMyRange As Range 'variabel untuk property object MyData

     'property dengan datatype long
     Public Property Get Nilai() As Long         'baca isi property
         Nilai = lMyNilai
     End Property

     Public Property Let Nilai(lNilai As Long)   'ubah isi property
         lMyNilai = lNilai
     End Property

     'property dengan datatype object
     Public Property Get MyData() As Range       'baca isi property
         Set MyData = rngMyRange
     End Property

     Public Property Set MyData(rng As Range)    'ubah isi property
         Set rngMyRange = rng
     End Property

  • variabel lMyNilai dan variabel obeject range rngMyRange adalah variabel yang akan dijadikan penyimpan nilai properti.
  • properti bernama Nilai akan menyimpan data di variabel lNilai, dan properti ber-datatype object bernama MyData akan menyimpan object-nya dalam variabel object range bernama rngMyRange.
  • Properti Nilai yang ber-datatype Long memiliki prosedur properti Let dan Get yang keduanya menggunakan Public. Artinya, properti Nilai memberi akses write melalui prosedur property Let dan memberi akses read melalui prosedur property Get.
  • Properti MyData yang ber-datatype object range memiliki prosedur Set dan Get yang keduanya menggunakan Public. Artinya, properti object MyData memberi akses write melalui prosedur property Set dan memberi akses read melalui prosedur property Get.
  • Jadi, untuk property ber-datatype object menggunakan prosedur property Set (untuk write) atau Get (untuk read). Selainnya menggunakan prosedur property Let (untuk write) dan Get (untuk read).
  • kemudian di general module lain, misal di mod11, ada prosedur yang bekerja memanfaatkan property Nilai dan MyData, sebagai berikut :
     Public Sub MemanfaatkanProperty()
         Dim rngA As Range, lNilB As Long
   
         'isi nilai ke dalam suatu variabel
         'melalui prosedur property let dan set

         Nilai = 5
         Set MyData = Range("a1")
   
         'ambil nilai dari suatu variabel
         'melalui prosedur property get

         lNilB = Nilai
         Set rngA = MyData
   
         'sekedar pesan
          MsgBox "Nilai lNilB : " & lNilB & vbCrLf & _
             "Alamat range dalam rngA : " & rngA.Address

     End Sub

  • Prosedur bernama MemanfaatkanProperty mengisi properti (proses write) Nilai pada baris berbunyi :
     Nilai = 5
  • Baris diatas dikerjakan dengan memanggil prosedur property Let Nilai.
  • Prosedur bernama MemanfaatkanProperty mengisi properti (proses write) object MyData pada baris berbunyi :
     Set MyData = Range("a1")
  • Baris diatas dikerjakan dengan memanggil prosedur property Set MyData karena properti MyData ber-type object.
  • Prosedur bernama MemanfaatkanProperty mengambil properti (proses read) Nilai dan MyData pada baris berbunyi :
     lNilB = Nilai
     Set rngA = MyData

  • Variabel lNilB akan diisi dengan isi properti bernama Nilai, yang diambil dengan cara menjalankan prosedur property Get Nilai.
  • Variabel object rngA akan di-set isinya dengan object yang ada dalam properti MyData, yang diambil dengan cara menjalankan prosedur property Get MyData.

Dari 2 buah general module di atas, variabel ber-scope module (menggunakan private), seperti variabel lMyNilai dan rngMyRange, bisa digunakan oleh prosedur yang ada dimodule lain dengan kehadiran prosedur jenis property. Cara mengaksesnya pun bisa layaknya menggunakan variabel yang ber-scopy project (menggunakan public).

Kasus diatas menggunakan prosedur property dalam sebuah general module. Proses yang dilakukan oleh prosedur jenis property Let, Set, dan Get bisa digantikan oleh prosedur jenis Sub dan Function. Pemakaian nama prosedur properti layaknya sebuah variabel tidak bisa dilakukan oleh prosedur function pengganti prosedur property get, melainkan hanya tampak seakan-akan bahwa nama prosedur function digunakan sebagai sebuah variabel.
  • misal dalam mod10 diberi prosedur function agar bisa berinteraksi dengan variabel lMyNilai secara langsung sebagai berikut :
     'bisa digunakan menjadi pengganti Get
     'dan bisa membantu mengatur ijin write

     Public Sub SimpanSiNilai(lIsinya As Long)
         lMyNilai = lIsinya
     End Sub
 

     'bisa digunakan menjadi pengganti Get
     'dan bisa membantu mengatur ijin read

     Public Function AmbilSiNilai() As Long
         AmbilSiNilai = lMyNilai
     End Function

  • cara memanfaatkannya adalah seperti prosedur bernama PakaiSubDanFunction di mod11 berikut ini :
     Public Sub PakaiSubDanFunction()
         Dim lNilB As Long
   
         'isi nilai ke dalam suatu variabel
         'melalui prosedur sub
         'sebagai pengganti prosedur property let

         SimpanSiNilai 5
   
         'ambil nilai dari suatu variabel
         'melalui prosedur function
         'sebagai pengganti prosedur property get

         lNilB = AmbilSiNilai
     End Sub

  • Jadi untuk menyimpan data bernilai 5 kedalam variabel lMyNilai dilakukan dengan memanggil prosedur Sub berargumen. Sedangkan untuk mengambil data dari variabel lMyNilai dilakukan dengan memanggil prosedur Function. Penataan ijin read atau write bisa dilakukan dengan mengubah scope public yang digunakan prosedur sub dan function seperti pengaturan public pada prosedur jenis property.
  • Prosedur property Let, Set, Get juga bisa digantikan oleh sebuah prosedur function. Misalkan untuk mengakses variabel lMyNilai seperti kasus di atas, bisa menggunakan prosedur function berikut :
     Public Function SiNilai( _
                                 Optional ByVal lIsinya As Long _
                               , Optional bWrite As Boolean _
                             ) As Long
         If bWrite Then
             lMyNilai = lIsinya
         End If
         SiNilai = lMyNilai
     End Function

  • Contoh penggunaannya adalah seperti dalam prosedur bernama PakaiFunctionSaja berikut ini :
     Public Sub PakaiFunctionSaja()
         Dim lNilB As Long
   
         'isi nilai ke dalam suatu variabel
         'melalui prosedur function SiNilai
         'sebagai pengganti prosedur property let

         SiNilai 5, True
   
         'ambil nilai dari suatu variabel
         'melalui prosedur function SiNilai
         'sebagai pengganti prosedur property get

         lNilB = SiNilai
     End Sub

  • Bentuknya cenderung lebih mirip dengan penggunaan prosedur jenis property. Nama prosedur yang sama bisa dipakai untuk proses read maupun write.


Prosedur property dalam Class Module

Bagian ini adalah perkenalan dengan class module. Class Module digunakan untuk membentuk sebuah custom class. Class adalah blueprint dari object yang dibentuk menggunakan class tersebut. Nama class module menjadi nama class pembentuk object.
  • Misalkan dibuat sebuah class module baru dan diberi nama cDataKu dengan cara :
  1. klik kanan sebuah module dalam project explorer -> pilih Insert -> pilih Class Module
  2. klik class module yang terbentuk -> lihat properties window -> ganti isi properti (Name) menjadi cDataKu
  • Salin script berikut ke dalam class module cDataKu :
     Private mRngData As Range

     Public Property Set DataRange(rng As Range)
         Set mRngData = rng
     End Property

     Public Property Get DataRange() As Range
         Set DataRange = mRngData
     End Property

  • Class cDataKu berisi sebuah property object bernama DataRange yang dibentuk menggunakan prosedur ber-scope project jenis Property Set dan Get agar memiliki akses read dan write. Nilai data akan disimpan dalam variabel mRngData yang ber-datatype Range atau dibentuk dari class Range.
  • Class cDataKu dapat digunakan oleh prosedur yang ada di module lain, seperti prosedur bernama PakaiCustomClass yang ada di general module mod11 berikut ini :
     Public Sub PakaiCustomClass()
         'deklarasi variabel object dari class cDataKu
         Dim oRng1 As cDataKu, oRng2 As cDataKu
   
         'deklarasi variabel object dari class Range
         Dim rngSatu As Range, rngDua As Range
   
         'instancing object dari class cDataku
         Set oRng1 = New cDataKu
         Set oRng2 = New cDataKu
   
         'ubah property DataRange milik object
         'dari class cDataKu

         Set oRng1.DataRange = Range("a1,b5:d5,c7:c9,f1:h3")
         Set oRng2.DataRange = Range("a1:k7")
   
         'ambil property DataRange milik object
         'dari class cDataKu

         Set rngSatu = oRng1.DataRange
         Set rngDua = oRng2.DataRange
   
          'sekedar tampilan pesan
          MsgBox "Isi property DataRange milik :" & vbCrLf & _
             "oRng1 adalah range " & oRng1.DataRange.Address _
             & vbCrLf & "oRng2 adalah range " & _
             oRng2.DataRange.Address & vbCrLf & vbCrLf & _
             "Perpotongan property DataRange dari " & _
             "oRng1 dengan oRng2 adalah range " & _
             Intersect(oRng1.DataRange, oRng2.DataRange).Address & _
             vbCrLf & vbCrLf & "Isi variabel range bernama :" & _
             vbCrLf & "rngSatu adalah range " & rngSatu.Address & _
             vbCrLf & "rngDua adalah range " & rngDua.Address & _
             vbCrLf & vbCrLf & _
             "Perpotongan rngSatu dengan rngDua adalah range " & _
             Intersect(rngSatu, rngDua).Address

     End Sub

  • Variabel oRng1 dan oRng2 akan memiliki datatype berupa object yang dibentuk menggunakan class cDataKu.
  • Variabel object oRng1 dan oRng2 tidak dapat digunakan sebelum diset instansinya (instancing). Proses instancing tersebut dilakukan oleh baris-baris kode :
     Set oRng1 = New cDataKu
     Set oRng2 = New cDataKu

  • Mengubah isi properti object bernama DataRange dari object oRng1 dan oRng2 dilakukan oleh baris-baris kode :
     Set oRng1.DataRange = Range("a1,b5:d5,c7:c9,f1:h3")
     Set oRng2.DataRange = Range("a1:k7")

  • Mengambil nilai properti object oRng1 dan oRng2 dilakukan oleh baris-baris kode :
     Set rngSatu = oRng1.DataRange
     Set rngDua = oRng2.DataRange
     MsgBox blablabla

  • Proses terhadap nilai properti bernama DataRange juga dapat dilihat dalam baris kode MsgBox blablabla.


Prosedur yang digunakan oleh banyak prosedur lain

Salah satu tantangan dalam menyusun program untuk sebuah proses otomasi maupun aplikasi adalah membuat prosedur yang bisa digunakan oleh banyak prosedur lain. Cobalah diingat-ingat tentang fitur Excel seperti sort. User bisa menggunakan Sort dimanapun didalam worksheet. Prosedur seperti untuk proses sort inilah yang dimaksud sebagai prosedur yang dapat digunakan oleh prosedur-prosedur lain. Contohnya sebagai berikut :
  1. Misalkan saja ada 5 sheet sumber data, bernama sheet1 sampai sheet5, yang data didalamnya akan digabungkan untuk masuk ke sheet bernama Data. Anggap saja proses terhadap semua sheet dimulai ketika sebuah tombol ditekan.
  2. Sheet1, Sheet3, dan Sheet4 akan menggunakan rangkaian proses bernama Proses Model A. Sedangkan Sheet2 dan Sheet5 akan menggunakan proses bernama Proses Model B.
  3. Proses Model A berisi rangkaian 7 proses, yang secara berurutan sebagai Proses1,Proses2,Proses3,Proses1,Proses4,Proses2,Proses1. Proses Model B berisi rangkaian 5 proses, yang secara berurutan sebagai Proses2,Proses1,Proses4,Proses1,Proses2. Data yang digunakan adalah data yang ada di setiap sheet yang diproses. Dari kedua model proses tersebut, dapat diketahui bahwa proses yang dibutuhkan adalah Proses1,Proses2,Proses3, dan Proses4 yang dipanggil dengan urutan sesuai model prosesnya, yaitu model A atau model B.
Secara singkat dapat dibentuk sebuah proses sebagai berikut :
  • Ketika tombol ditekan, akan dijalankan sebuah prosedur yang dipanggil oleh si tombol. Misalkan namanya adalah Prosedur Tombol.
  • Prosedur Tombol akan berisi proses perulangan membaca setiap sheet, yaitu sheet1 sampai sheet5 silih berganti, yang dapat berupa penggunaan For Each Next.
  • Dalam blok perulangan akan ada analisa terhadap nama sheet. Jika nama sheet masuk kelompok Sheet1,Sheet3, dan Sheet4, maka proses akan memanggil prosedur bernama ProsesModelA. Jika nama sheet masuk kelompok lainnya, maka proses akan memanggil prosedur bernama ProsesModelB.
  • Kira-kira bunyi prosedur bernama Tombol akan berbunyi :
     Public Sub Tombol()
         Dim sht As Worksheet
   
         For Each sht In Sheets( _

                Array("Sheet1", "Sheet2", "Sheet3", "Sheet4", "Sheet5") _
                          )
             sht.Activate
             Select Case sht.Name
             Case "Sheet1", "Sheet3", "Sheet4"
                 ProsesModelA
             Case "Sheet2", "Sheet5"
                 ProsesModelB
             End Select
         Next sht
         Sheets("Data").Activate
     End Sub

  • Karena proses akan masuk ke Proses Model A atau Proses Model B, maka dibentuklah prosedur untuk kedua proses tersebut dan diletakkan dalam module yang sama.
  • Proses Model A bisa dibuatkan dalam prosedur bernama ProsesModelA. Proses yang dijalankan dalam ProsesModelA adalah menjalankan Proses1,Proses2,Proses3,Proses4 dalam suatu urutan tertentu. Bentuk prosedur ProsesModelA dapat berbentuk :
     Public Sub ProsesModelA()
         'rangkaian proses di Proses Model A adalah
         'Proses1,Proses2,Proses3,Proses1,Proses4,Proses2,Proses1

         MsgBox "ProsesModelA mulai"
         Proses1
         Proses2
         Proses3
         Proses1
         Proses4
         Proses2
         Proses1
         MsgBox "ProsesModelA selesai"
     End Sub

  • Proses Model B bisa dibuatkan dalam prosedur bernama ProsesModelB. Proses yang dijalankan dalam ProsesModelB adalah menjalankan Proses1,Proses2,Proses4 dalam suatu urutan tertentu. Bentuk prosedur ProsesModelB dapat berbentuk :
     Public Sub ProsesModelB()
         'rangkaian proses di Proses Model B adalah
         'Proses2,Proses1,Proses4,Proses1,Proses2

         MsgBox "ProsesModelB mulai"
         Proses2
         Proses1
         Proses4
         Proses1
         Proses2
         MsgBox "ProsesModelB selesai"
     End Sub

  • Pemilihan scope project dengan menggunakan keyword Public pada deklarasi prosedur ProsesModelA dan ProsesModelB akan membuat kedua proses tersebut dapat digunakan oleh prosedur lain selain prosedur Tombol. Baik yang ada dalam module tersebut atau yang ada di modeul lainnya.
  • Proses-proses yang dijalankan pada Proses Model A dan Proses Model B dibuat dalam prosedur tersendiri berdasar karakteristik prosesnya. Karena proses yang dijalankan memiliki 4 karakteristik proses, maka dibuatlah 4 prosedur proses tersebut sebagai berikut : (diletakkan dalam module yang sama dengan prosedur ProsesModelA dan ProsesModelB)
     Private Sub Proses1()
         'baris-baris kode proses1
         'misalkan ada 10 baris kode

     End Sub

     Private Sub Proses2()
         'baris-baris kode proses2
         'misalkan ada 20 baris kode

     End Sub

     Private Sub Proses3()
         'baris-baris kode proses3
         'misalkan ada 30 baris kode

     End Sub

     Private Sub Proses4()
         'baris-baris kode proses4
         'misalkan ada 40 baris kode

     End Sub

  • Prosedur-prosedur proses dibuat terpisah atau per prosedur sesuai karakteristik prosesnya.
  • Bisa jadi jumlah baris kodenya akan sama ataupun berbeda-beda.
  • Dengan terpisahnya menjadi prosedur-prosedur yang tersendiri, maka dapat dibuat banyak model proses seperti ProsesModelC, ProsesModelD, dan sebagainya yang bisa jadi juga membutuhkan prosedur-prosedur proses tersebut.
  • Perbaikan sebuah proses dapat lebih fokus ke prosedur proses tersebut dan tidak kuatir ada bagian proses yang sama yang belum diperbaiki.
  • Penggunaan scope module dengan keyword private akan mengurangi daftar prosedur yang bisa di-Run dari workbook window di dialog Macro.

Cara penyusunan prosedur seperti kasus diatas akan menghasilkan baris kode (tanpa baris deklarasi) sebagai berikut :
  •  11 baris kode prosedur Tombol
  •   9 baris kode prosedur ProsesModelA
  •   7 baris kode prosedur ProsesModelB
  •  10 baris kode prosedur Proses1
  •  20 baris kode prosedur Proses2
  •  30 baris kode prosedur Proses3
  •  40 baris kode prosedur Proses4
  • 127 total baris kode untuk seluruh kegiatan

Coba bayangkan andai saja ProsesModelA disusun seperti prosedur ProsesModelA1 berikut ini :
     Public Sub ProsesModelA1()
         'rangkaian proses di Proses Model A1 adalah
         'Proses1,Proses2,Proses3,Proses1,Proses4,Proses2,Proses1

         MsgBox "ProsesModelA1 mulai"
   
         'baris-baris kode proses1
         'misalkan ada 10 baris kode
   
         'baris-baris kode proses2
         'misalkan ada 20 baris kode
   
         'baris-baris kode proses3
         'misalkan ada 30 baris kode
   
         'baris-baris kode proses1
         'misalkan ada 10 baris kode
   
         'baris-baris kode proses4
         'misalkan ada 40 baris kode
   
         'baris-baris kode proses2
         'misalkan ada 20 baris kode
   
         'baris-baris kode proses1
         'misalkan ada 10 baris kode

   
         MsgBox "ProsesModelA1 selesai"
     End Sub

Maka prosedur ProsesModelA1 saja sudah berisi 142 baris kode. Selain itu, jika akan memperbaiki proses1, maka pada prosedur ProsesModelA seperti ini harus dilakukan pada 3 tempat. Belum lagi nanti yang ada di prosedur model-model lainnya, seperti ProsesModelB1.

Pembahasan tentang prosedur selesai dulu sampai disini. Harapannya, penyusunan prosedur untuk suatu proses bisa lebih spesifik sesuai karakteristik prosesnya, sehingga prosedur-prosedur dengan karakteristik yang memungkinkan untuk digunakan dalam proses lainnya bisa dijalankan dengan memanggil nama prosedur proses tertentu tersebut. Seperti halnya proses yang memiliki karakteristik proses seperti Proses1 bisa digunakan dalam prosedur-prosedur model proses lainnya.

Insya Allah pembahasan selanjutnya adalah tentang object utama dalam Excel seperti Application, Workbook, Worksheet, dan Range.




Sunday, July 14, 2013

BelajarVBA 005 - Procedure seri 2

Coretan Mr. Kid

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
Keuntungan-keuntungan tersebut adalah sebagian keuntungan dari bagian awal dari usaha penyusunan alur program yang bersifat modular. Salah satu tantangan utama dalam membuat sebuah program atau aplikasi adalah membuat prosedur-prosedur yang tingkat kegunaannya tinggi karena bisa digunakan oleh banyak prosedur lain.

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 :
     Dim lAtmSiYani As Long
  • variabel lAtmSiYani diisi dengan nilai 32, yang sejatinya adalah menyimpan nilai 32 ke dalam memori, oleh baris kode :
     lAtmSiYani = 32
  • 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 :
     lKertasSiOtong = 7
  • 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 :
     MsgBox "Nilai dalam variabel lAtmSiYani :" & lAtmSiYani
  • 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 :
     Dim lRekeningSiGaluh As Long
  • variabel lRekeningSiGaluh diisi dengan nilai 12, yang sejatinya adalah menyimpan nilai 12 ke dalam memori, oleh baris kode :
     lRekeningSiGaluh = 12
  • 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 :
     lDompetSiAgus = 5
  • 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 :
     MsgBox "Nilai dalam variabel lRekeningSiGaluh :" & lRekeningSiGaluh
  • 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.
     Private Function TotalDiscount( _
                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.
     Public Sub Perhitungan()
       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 curSales As Currency
     Dim curDiscount As Currency
     Dim curProfit As Currency

  • Nilai penjualan disimpan dalam curSales dan persentase discount disimpan dalam curDiscount pada baris-baris kode :
     curSales = 1000
     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 :
     curDiscount = TotalDiscount(curDiscount, curSales, curProfit)
  • 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 :
     TotalDiscount = curDisc * curJual
  • Profit dihitung dan hasilnya disimpan ke lokasi memori curNetJual melalui baris kode :
     curNetJual = curJual - TotalDiscount
  • 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 :
     MsgBox "Nilai jual = " & curSales & vbCrLf & _
            "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.


Saturday, July 13, 2013

Pencarian Khusus Tentang Excel

Rekan-rekan b-eXcel,

Blog kita sekarang sudah dilengkapi dengan sumber-sumber belajar Excel berbahasa Indonesia yang tersebar di Internet. Lihat di bagian kanan-bawah.

Dengan demikian, rekan-rekan tidak perlu mengingat banyak URL lagi, tapi cukup datang ke blog ini dan melihat hasil postingan terbaru dari sumber tersebut.

Selain itu, blog ini pun sekarang dilengkapi dengan fasilitas Pencarian (lihat di sebelah kanan), dimana rekan-rekan bisa langsung mencari keyword tertentu dalam blog ini, atau meluaskan pencarian ke seluruh sumber yang sudah di-link ke blog ini. Cukup memudahkan, bukan?



Semoga bermanfaat.

Komentar, saran, dan masukan silahkan dikirimkan ke Admin (haertalib@gmail.com)

BelajarVBA 005 - Procedure seri 1


Coretan Mr. Kid


Harta akan terasa habis yang ada ditangan ketika dibagikan, sedangkan ilmu tidak pernah habis ketika dibagikan

Pada BelajarVBA 002 telah disinggung sedikit tentang prosedur, yaitu pengertian dan bentuk dasar sebuah prosedur. Pada pembahasan kali ini, akan kita jelajahi lebih jauh tentang seluk beluk prosedur. Mulai dari jenisnya hingga penggunaan prosedur yang dideklarasikan secara lengkap. Untuk memudahkan proses belajar, maka file BelajarVBA004.xlsm bisa menjadi media untuk mencoba secara langsung hal-hal yang dijabarkan dalam pembahasan kali ini. File BelajarVBA004.xlsm bisa diunduh disini. Pembahasan kali ini adalah seri pertama dari tiga seri pembahasan tentang prosedur.



Jenis Prosedur

Prosedur di dalam VBA ada 3 (tiga) jenis, yaitu :

Sub

Prosedur yang berisi proses kerja tanpa memberikan nilai balik hasil kerja. Jadi nama prosedur tidak menyimpan nilai apapun. Prosedur jenis sub yang dideklarasikan dengan keyword Public dan tanpa parameter input apapun dapat dijalankan melalui workbook window sebagai sesuatu yang sering disebut Macro.
Misalkan pada general module bernama mod02 diberi prosedur berikut ini :
   Public Sub LuasPakaiSub()
     Dim lPanjang As Long, lLebar As Long, lLuas As Long
     lPanjang = 5
     lLebar = 8
     lLuas = lPanjang * lLebar
   End Sub

Ketika prosedur sub bernama LuasPakaiSub dijalankan, maka variabel lPanjang akan diisi nilai 5, lLebar diisi nilai 8, dan Luas akan dihitung sebagai lPanjang * lLebar yang menghasilkan 5 * 8 = 40 yang disimpan dalam variabel lLuas. Nilai 40 ini tidak dapat disimpan dalam nama prosedur sub. Jadi prosedur sub tidak menghasilkan apapun selain sebuah kerja dan berlalu begitu saja setelah selesai kerja.
Proses untuk menjalankannya sebagai Macro adalah pada
     ribbon Developer -> group Code -> Macro
atau dengan menekan tombol ALT F8 bersamaan, yang dilanjutkan dengan memilih nama prosedur sub yang akan dijalankan dan diikuti menekan tombol Run yang ada dalam dialog window Macro yang ada.

Function

Prosedur yang berisi proses kerja yang menghasilkan suatu nilai balik hasil kerja. Nilai balik hasil kerja disimpan dalam nama prosedur. Prosedur function yang dideklarasikan dengan keyword Public dapat digunakan dalam cell seperti fungsi bawaan Excel.
Misalkan pada general module bernama mod02 diberi prosedur berikut ini :
   Public Function LuasPakaiFunction() As Long
     Dim lPanjang As Long, lLebar As Long
     lPanjang = 5
     lLebar = 8
     LuasPakaiFunction = lPanjang * lLebar
   End Function

Prosedur function menggunakan keyword Function dan disertai pernyataan As datatype tertentu seperti As Long. Pada prosedur sub menggunakan keyword Sub dan tidak ada penambahan apapun diakhir deklarasi.
Ketika prosedur function bernama LuasPakaiFunction dijalankan, maka variabel lPanjang akan diisi nilai 5, lLebar diisi nilai 8, dan Luas akan dihitung sebagai lPanjang * lLebar yang menghasilkan 5 * 8 = 40 yang disimpan dalam nama prosedur function, yaitu LuasPakaiFunction. Jadi nama prosedur function, yaitu LuasPakaiFunction akan berisi nilai 40. Jika hasil proses yang disimpan oleh nama prosedur function tersebut tidak segera disimpan ke sebuah variabel oleh kode program yang menjalankannya, maka nilai tersebut akan segera hilang.
Pemanggilan kembali LuasPakaiFunction akan berarti melakukan proses yang baru dan bukan mengambil nilai yang disimpan saat menjalankan prosedur tersebut sebelumnya. Oleh sebab itu, maka pemanggilan prosedur function sering digunakan sebagai salah satu sarana untuk mengisi nilai suatu variabel disebuah proses yang sedang dijalankan pada prosedur lain. Misalkan di general module mod03 diberi prosedur sub yang membutuhkan hasil kerja prosedur function di atas sebagai berikut :
   Public Sub ButuhHasilFunction()
     Dim lLuas As Long
     lLuas = LuasPakaiFunction
   End Sub

Ketika prosedur sub bernama ButuhHasilFunction, maka variabel lLuas akan diisi oleh hasil proses di dalam prosedur function bernama LuasPakaiFunction. Dalam hal ini, nilai yang disimpan oleh variabel lLuas akan bernilai 40 karena hasil kerja prosedur function bernama LuasPakaiFunction menghasilkan nilai 40.
Jika prosedur function akan digunakan layaknya sebuah prosedur Sub, maka pemanggilannya adalah dengan menggunakan keyword Call, seperti Call LuasPakaiFunction. Nilai balik dari function tidak akan disimpan.
Prosedur function bernama LuasPakaiFunction juga dapat digunakan dalam cell karena deklarasi prosedur LuasPakaiFunction adalah menggunakan keyword Public. Misalkan saat berada dalam workbook window pada sheet Kerja dan di cell B5 diberi formula berbunyi :
     =LuasPakaiFunction()
Maka di cell B5 akan muncul hasil kerja fungsi LuasPakaiFunction yang berupa prosedur function bernama LuasPakaiFunction. Dalam hal ini, akan muncul nilai 40.

Property

Prosedur yang digunakan untuk mengisi nilai ke sebuah variabel atau mengambil nilai dari sebuah variabel. Umumnya jenis prosedur property digunakan secara intensif ketika membentuk sebuah custom class dalam Class Module. Jadi, pada dasarnya, prosedur jenis ini bisa digunakan dimana saja seperti halnya prosedur jenis Sub maupun Function.
Prosedur property terdiri dari :
  • Let : untuk memasukkan nilai kedalam variabel selain object dan kerjanya mirip dengan penggunaan jenis Sub
  • Set : untuk memasukkan nilai kedalam variabel object dan kerjanya mirip dengan penggunaan jenis sub
  • Get : untuk mengambil nilai dari suatu variabel dan kerjanya mirip dengan jenis Function
Pembahasan tentang property akan dilanjutkan setelah memahami Sub dan Function lebih detil.


Deklarasi Prosedur

Sebuah contoh deklarasi prosedur sub yang diletakkan pada sebuah general module (misal di mod04) adalah sebagai berikut :
   Public Sub DataMember _
               ( _
                    sNama As String _
                   ,ByVal lUmur As Long _
                   ,lAnak As Long _
                   ,ByRef sAlamat As String _
                   ,Optional ByVal sTelp As String _
                   ,Optional ByRef sEmail As String _
                   ,Optional bMember As Boolean =TRUE _
               )
     'kode program disini
   End Sub

Argumen

Setiap bentuk yang seperti suatu deklarasi variabel, misal sNama As String, disebut sebuah argumen. Prosedur bisa berisi banyak argumen. Contoh di atas berisi 7 argumen. Argumen terdiri dari nama argumen (misal sNama) dan datatype argumen (misal As String). Nama argumen bekerja layaknya variabel didalam prosedur tersebut (scope level local). Argumen adalah sesuatu yang harus disediakan oleh prosedur lain yang bermaksud memanggil prosedur berargumen ini, yang berupa sebuah nilai input parameter. Jadi, prosedur lain yang akan menggunakan prosedur DataMember di atas harus menyediakan nilai bagi setiap argumen yang harus dipenuhi.

Keyword Optional

Keyword Optional digunakan untuk menyatakan bahwa argumen tersebut boleh tidak disediakan nilainya. Penggunaan keyword Optional bisa disertai dengan penetapan nilai default bagi argumen tersebut ketika tidak disediakan nilainya ooeh prosedur pemanggil, seperti =TRUE pada Optional bMember As Boolean =TRUE. Setiap argumen dengan keyword optional dikumpulkan dan diletakkan pada bagian akhir daftar argumen, seperti jejeran argumen yang menggunakan keyword optional pada contoh diatas. Pada contoh di atas, bila argumen bMember tidak diberi nilai oleh prosedur pemanggil, maka akan diisi oleh nilai default menurut baris deklarasi tersebut, yaitu bernilai TRUE.

Keyword ByVal dan ByRef

Keyword ByVal dan ByRef adalah penunjuk cara penggunaan sesuatu yang diserahkan oleh prosedur pemanggil kepada prosedur berargumen yang dipanggil. ByRef adalah sebagai default, sehingga sNama As String dapat ditulis sebagai ByRef sNama As String.
Keyword ByVal berarti argumen akan diisi dengan salinan data. Prosedur berargumen di atas hanya akan mengubah salinan nilai dan nilai asli tidak akan berubah sama sekali. Contohnya adalah lUmur. Prosedur pemanggil memberikan nilai 17 untuk argumen lUmur milik prosedur DataMember. Proses dalam prosedur DataMember mengubah isi lUmur dari 17 menjadi 23. Maka prosedur pemanggil, yaitu yang menyerahkan nilai 17 kepada argumen lUmur milik prosedur DataMember, tetap berisi nilai 17.
Keyword ByRef berarti argumen akan diisi dengan wujud data tersebut secara langsung. Contohnya adalah sAlamat. Prosedur pemanggil memberikan nilai 'Batam' untuk sAlamat milik prosedur DataMember. Proses dalam prosedur DataMember mengubah isi nilai 'Batam' menjadi 'Jakarta'. Maka prosedur pemanggil, yaitu yang menyerahkan nilai 'Batam' kepada argumen sAlamat milik prosedur DataMember, akan mendapati bahwa isi dirinya telah berubah menjadi 'Jakarta'.

Cara memanggil prosedur berargumen

Prosedur yang memiliki argumen harus disediakan nilai data setiap argumen utamanya (tanpa Optional) agar bersedia bekerja. Misalkan akan memanggil prosedur sub berargumen seperti prosedur DataMember yang diletakkan pada general module bernama mod04 yang menjadi contoh di atas tadi. Pada general module bernama mod03 bisa diberi prosedur pemanggil seperti prosedur berikut ini :
   Public Sub PanggilBerargumen1()
     'diisi nilai konstan secara langsung untuk semua argumen
     DataMember "Kid", 17, 0, "Jakarta", _
                "021-12345678", "mr.nmkid@gmail.com", True
   End Sub

Nilai 'Kid' yang berdatatype String akan mengisi argumen sNama. Nilai 17 dan 0 yang berdatatype Long akan secara berurutan mengisi argumen lUmur dan lAnak. Nilai 'Jakarta' akan mengisi argumen sAlamat. Sedangkan nilai berdatatype string '021-12345678' dan 'mr.nmkid@gmail.com' akan mengisi argumen sTelp dan sEmail yang bersifat optional (bila ada atau bila dibutuhkan) secara berurutan. Nilai Boolean TRUE akan mengisi argumen bMember yang juga bersifat optional.
Saat mengetikkan spasi setelah nama prosedur DataMember, akan muncul tooltip info tentang nama prosedur beserta argumen yang dibutuhkan seperti gambar berikut ini :
Pada gambar tersebut tampak nama prosedur, yaitu DataMember, yang memiliki banyak argumen, mulai dari sNama yang harus dipenuhi sampai dengan bMember yang bersifat optional (bila ada atau bila dibutuhkan).
Tooltip info muncul karena item Auto Quick Info tercentang. Item ini dapat ditemukan pada Options (menu Tools -> Options) di tab Editor bagian Code Settings.

Cara memanggil prosedur DataMember dengan menggunakan keyword Call akan berbentuk seperti prosedur berikut :
   Public Sub PanggilBerargumen2()
     'diisi nilai konstan secara langsung untuk semua argumen
     'dengan menggunakan keyword Call
     Call DataMember("Kid", 17, 0, "Jakarta", _
                "021-12345678", "mr.nmkid@gmail.com", True)
   End Sub

Pengisian argumen pada prosedur PanggilBerargumen2 tetap berurutan seperti pada prosedur PanggilBerargumen1. Perbedaan cara pemanggilan prosedur DataMember antara yang menggunakan keyword Call (dalam PanggilBerargumen2) dengan yang tidak menggunakan keyword Call (dalam PanggilBerargumen1) adalah keberadaan keyword Call dan penggunaan tanda kurung. Pada pemanggilan dengan keyword Call dibutuhkan adanya tanda kurung yang melingkupi seluruh nilai argumen yang akan diserahkan ke prosedur yang dipanggil, yang dalam hal ini adalah prosedur DataMember.
Pada contoh pemanggilan di atas, argumen bMember diisi dengan nilai TRUE. Pada deklarasi prosedur DataMember, argumen bMember bersifat optional dan dinyatakan bahwa nilai default-nya adalah TRUE. Maka pemanggilan prosedur DataMember untuk nilai bMember yang juga bernilai TRUE dapat dikosongkan seperti prosedur PanggilBerargumen3 berikut :
   Public Sub PanggilBerargumen3()
     'diisi nilai konstan secara langsung
     'untuk bMember yang akan diisi TRUE
     'yang sesuai nilai default bMember

     DataMember "Kid", 17, 0, "Jakarta", _
                "021-12345678", "mr.nmkid@gmail.com"
   
     'diisi nilai konstan secara langsung
     'dengan menggunakan keyword Call
     'untuk bMember yang akan diisi TRUE
     'yang sesuai nilai default bMember

     Call DataMember("Kid", 17, 0, "Jakarta", _
                "021-12345678", "mr.nmkid@gmail.com")
   End Sub

Jadi, nilai TRUE tidak perlu ditulis dalam pemanggilannya. Pada contoh di atas, bMember ada dibagian akhir deklarasi. Argumen yang bersifat optional lainnya, seperti sTelp, tidak ditentukan nilai default-nya. Maka nilai default dari argumen sTelp adalah nilai default dari datatype yang digunakan oleh sTelp. Karena sTelp menggunakan datatype String, maka nilai default-nya adalah NULLSTRING atau teks kosong.
Jika argumen sTelp yang bersifat optional tidak ingin diisi sesuatu atau ingin menggunakan nilai default dari argumen sTelp, maka pemanggilan prosedur DataMember akan menjadi seperti dalam prosedur PanggilBerargumen4 berikut ini :
   Public Sub PanggilBerargumen4()
     'diisi nilai konstan secara langsung
     'untuk bMember yang akan diisi TRUE
     'yang sesuai nilai default bMember
     'dan argumen sTelp akan diisi sesuai defaultnya

     DataMember "Kid", 17, 0, "Jakarta", , "mr.nmkid@gmail.com"
   
     'diisi nilai konstan secara langsung
     'dengan menggunakan keyword Call
     'untuk bMember yang akan diisi TRUE
     'yang sesuai nilai default bMember
     'dan argumen sTelp akan diisi sesuai defaultnya

     Call DataMember("Kid", 17, 0, "Jakarta", , "mr.nmkid@gmail.com")
   End Sub

Kehadiran sebuah item kosong antara nilai untuk argumen sAlamat (yang bernilai 'Jakarta') dengan nilai untuk argumen sEmail (yang bernilai 'mr.nmkid@gmail.com') menunjukkan bahwa argumen sTelp tidak disediakan nilainya oleh prosedur PanggilBerargumen4 yang menjadi prosedur pemanggil prosedur DataMember. Pemanggilan seperti di atas, baik dengan atau tanpa keyword Call, akan membuat argumen sTelp diisi dengan NULLSTRING yang menjadi nilai default.

Nama argumen dari prosedur yang dipanggil juga bisa dituliskan agar lebih mudah pembacaan kode programnya dilain waktu. Misal, cara pemanggilan prosedur PanggilBerargumen1 akan menyertakan nama-nama argumennya, maka akan seperti prosedur PanggilBerargumen5 berikut ini :
   Public Sub PanggilBerargumen5()
     'diisi nilai konstan secara langsung untuk semua argumen
     DataMember _
        sNama:="Kid" _
        , lUmur:=17 _
        , lAnak:=0 _
        , sAlamat:="Jakarta" _
        , sTelp:="021-12345678" _
        , sEmail:="mr.nmkid@gmail.com" _
        , bMember:=True
   End Sub

Pada contoh prosedur bernama PanggilBerargumen5 tampak bahwa nama argumen selalu diikuti dengan karakter titik dua dan sama dengan ( := ). Ketika ada nama argumen yang disertakan dalam pemanggilan, maka seluruh argumen setelah nama argumen pertama yang tertulis juga harus dituliskan. Pada contoh di atas, dikarenakan argumen sNama ditulis nama argumennya, yaitu berbunyi sNama:=, maka seluruh argumen setelah sNama harus menyertakan nama argumennya.
Jika argumen sNama dan lUmur tidak menyertakan nama argumennya, tetapi argumen lAnak menyertakan argumennya, maka argumen sAlamat sampai dengan bMember harus menyertakan nama argumennya jika akan diset nilainya. Contohnya seperti prosedur PanggilBerargumen6 berikut ini :
   Public Sub PanggilBerargumen6()
     'diisi nilai konstan secara langsung untuk semua argumen
     'Argumen sNama dan lUmur tidak menyertakan nama argumen
     'Argumen lAnak menyertakan nama argumen,
     'maka argumen sAlamat sampai bMember
     'harus menyertakan nama argumen

     DataMember "Kid", 17 _
        , lAnak:=0 _
        , sAlamat:="Jakarta" _
        , sTelp:="021-12345678" _
        , sEmail:="mr.nmkid@gmail.com" _
        , bMember:=True
   End Sub


Penyertaan nama argumen akan terasa manfaatnya ketika berhubungan dengan argumen-argumen yang bersifat optional yang tidak seluruhnya akan diisi nilai. Pada contoh prosedur DataMember, penyertaan argumen akan terasa ketika akan mengisi argumen sTelp sampai bMember. Misalkan saja seperti pemanggilan prosedur DataMember seperti contoh prosedur PanggilBerargumen4 yang hanya akan mengisi argumen bersifat optional bernama sEmail saja. Ketika menyertakan nama argumen, maka prosedur PanggilBerargumen4 bisa diubah seperti prosedur PanggilBerargumen7 berikut ini :
   Public Sub PanggilBerargumen7()
     'argumen optional yang diisi hanya sEmail saja
     DataMember "Kid", 17, 0, "Jakarta" _
            , sEmail:="mr.nmkid@gmail.com"

     'argumen optional yang diisi hanya sEmail saja
     'dengan keyword Call

     Call DataMember("Kid", 17, 0, "Jakarta" _
            , sEmail:="mr.nmkid@gmail.com")
   End Sub

Pada prosedur PanggilBerargumen7 tampak bahwa argumen sNama sampai dengan argumen sAlamat yang harus dipenuhi (bukan bersifat optional) ditulis tanpa menyertakan nama argumen. Sedangkan pada satu-satunya argumen bersifat optional yang akan diisi, yaitu argumen bernama sEmail, disertai dengan nama argumennya. Dengan cara ini, maka tidak diperlukan adanya ruang kosong antara nilai 'Jakarta' (untuk argumen sAlamat) dengan nilai 'mr.nmkid@gmail.com' (untuk argumen optional sEmail).
Hal ini akan terasa manfaatnya ketika jumlah argumen optionalnya sangat banyak seperti contohnya pada pemanggilan prosedur sub Sort yang menjadi sebuah methods (kemampuan kerja) dari object range. Prosedur Sort memiliki banyak sekali argumen. Pada prosedur Sort, seluruh argumen bersifat Optional. Misalkan akan melakukan sort terhadap area A1:C5 yang memiliki header pada area A1:C1 berdasar kolom B secara Ascending. Kegiatan ini akan memerlukan nilai input parameter untuk argumen berupa :
  • kolom kunci sort, yaitu kolom B yang diwakili oleh Range("b1") sebagai pengisi argumen Key1
  • cara mengurutkan secara Ascending yang menjadi nilai default dari argumen Order1, sehingga bisa dikosongkan saja
  • informasi tentang keberadaan header untuk argumen bernama Header yang memiliki nilai default xlNo, yang akan diisi dengan nilai xlYes karena area A1:C5 memiliki header di area A1:C1.
Contoh prosedur untuk proses ini akan seperti gambar berikut :
Dari gambar di atas tampak bahwa prosedur sort memiliki argumen dari Key1 sampai dengan DataOption3 yang bersifat optional dan beberapa diantara argumen tersebut telah ditetapkan nilai defaultnya. Untuk proses sort pada kasus ini cukup mengisi argumen Key1 dan argumen Header saja. Argumen Order1 diabaikan karena nilai defaultnya sudah sesuai dengan kebutuhan, yaitu secara Ascending. Argumen Key2 sampai dengan Order3 diabaikan karena tidak dibutuhkan. Begitu juga dengan argumen OrderCustom sampai dengan DataOption3 yang diabaikan karena tidak dibutuhkan.
Penyertaan nama argumen bisa memberi banyak manfaat, antara lain adalah :
  • Kemudahan untuk tetap fokus pada penyediaan nilai-nilai argumen yang dibutuhkan saja
  • Meringkaskan baris kode program, terutama pada kasus-kasus yang berinteraksi dengan prosedur yang memiliki banyak argumen bersifat optional
  • Kemudahan dalam membaca kode program dilain waktu oleh programmer lain

Dari uraian di atas semestinya sudah bisa mulai terbayang tentang adanya potensi untuk membuat sebuah proses dalam sebuah prosedur atau serangkaian prosedur yang bisa digunakan berulang-ulang oleh banyak prosedur kerja. Contohnya seperti prosedur sort yang bisa digunakan oleh banyak kegiatan sort tanpa harus selalu menulis algoritma proses perulangan (loop) untuk mengurutkan data.

Insya Allah pembahasan prosedur pada seri kedua adalah tentang ByRef dan ByVal serta pemanfaatan scope untuk membuat sebuah rangkaian proses lebih bersifat modular. Pemahaman tentang scope, variabel, dan prosedur berargumen akan lebih intensif dibahas dan digunakan.