Laman

BelajarVBA 102 - ComboBox 01

Coretan Mr. Kid

Sempatkan berbagi sebelum sempit.

Setelah sekian lama tak sempat, Alhamdulillah tiba juga masa sempat tersebut. Bahasan kali ini tentang ActiveX ComboBox. ActiveX Controls memiliki banyak properti dan event yang memudahkan pengaturan alur proses menampilkan sesuatu. Salah satu ActiveX Controls yang sering digunakan adalah ComboBox. File yang digunakan mendampingi coretan kali ini adalah BelajarVBA102_01.xlsm.



ComboBox

Object control ini dapat digunakan untuk menampilkan daftar pilihan kepada user. Daftar pilihan bisa disertai beberapa kolom tambahan yang dapat dijadikan sebagai informasi tambahan bagi user. Object control ini dapat digunakan di dalam Worksheet maupun di dalam UserForm.

Selain dengan cara memilih dari pilihan yang tersedia, user juga bisa menuliskan nama item yang dibutuhkannya pada suatu area penulisan layaknya menulis pada sebuah textbox. Jika yang ditulis user ada dalam daftar pilihan, maka combobox akan segera memilihkan item tersebut untuk user.

Jadi, combobox memiliki 2 bagian utama, yaitu :
  1. daftar pilihan
    • Pada umumnya, daftar ini ditampilkan bila user meng-click dropdown, tetapi pengaturan properti untuk hal ini bisa dilakukan pada properti bernama ShowDropButtonWhen
    • Daftar pilihan ditampilkan sebagai sebuah list yang mirip dengan control ListBox dan memiliki karakteristik (properti, methods, events) yang sebagian besar sama dengan listbox.
  2. penulisan nama item
    • Area penulisan ini memiliki karakteristik (properti, methods, events) yang sebagian besar sama dengan control TextBox.
    • Teks yang di-input akan membuat combobox berusaha mencari dan memilihkan item dari dalam daftar pilihan. Karakteristik pencarian dan pemilihan item yang dilakukan oleh combobox akibat inputan dapat diatur pada properti MatchEntry dan MatchRequired.
Data yang akan digunakan sebagai daftar pilihan dalam combobox adalah seperti gambar berikut :

Properti ListFillRange dan LinkedCell

Bahasan pertama adalah tentang combobox yang diletakkan di dalam sebuah worksheet (misal worksheet bernama list_fill_range). Ketika daftar item yang akan dipasang pada combobox berada di suatu area range, sebut saja pada range A2:A5 (lihat gambar data di atas dan anggap saja data tersebut ada di sheet list_fill_range), maka properti ListFillRange bisa memberi kemudahan. Pengisian daftar item dalam combobox bisa dilakukan dengan mengisi properti ListFillRange. Isi properti ListFillRange adalah alamat area range dari daftar item, seperti menuliskan teks berbunyi A2:A5. Properti dari combobox bisa dimunculkan ketika dalam keadaan Design Mode (lihat di ribbon Developer dan klik Design Mode). Cara menampilkan window properties dari si object adalah dengan klik kanan si object dan pilih Properties.

Setelah daftar terisi dan Design Mode telah di-off-kan, maka user bisa memilih sebuah item dari daftar yang ada. Pilihan user ini bisa dituliskan ke sebuah cell tanpa perlu script VBA dengan memanfaatkan properti bernama LinkedCell. Isian properti LinkedCell juga berupa alamat sebuah range. Misalkan, pada properti LinkCell diisi alamat range berbunyi B10. Setiap kali user memilih sebuah item dari combobox, maka pada cell B10 akan tertulis pilihan user tersebut. Ketika user mengosongkan pilihan atau menulis sesuatu dalam combobox yang tidak ada di dalam daftar, maka cell B10 akan berisi error value #N/A.

Gambar berikut ini adalah cuplikan dari sheet bernama list_fill_range pada file yang disebutkan di atas.

Jadi, properti :
  • ListFillRange : untuk mengisi daftar combobox atau listbox dari suatu area range.
  • LinkedCell : untuk mengikatkan properti Value milik object ke sebuah range.

Multiple Column dan Event Change

Pengaturan yang dilakukan pada properti combobox agar bisa menampilkan banyak kolom informasi tambahan adalah sebagai berikut :
  • ColumnCount : jumlah kolom yang ditampilkan pada list. Jadi, list bisa berisi lebih banyak kolom dibanding yang ditampilkan. Misalkan list berisi 8 kolom, tetapi hanya ditampilkan 5 kolom saja dengan mengisi ColumnCount dengan nilai 5.
  • ColumnHeads : status menampilkan header atau tidak (TRUE/FALSE) ketika sumber data dari suatu area range.
  • ColumnWidths : pengaturan lebar masing-masing kolom dalam satuan point (pt) yang dipisah karakter titik koma ( ; ), seperti 60pt;80pt;80pt untuk 3 kolom yang ditampilkan.
  • ListWidth : lebar list keseluruhan dalam satuan point (pt) ketika dimunculkan atau saat user mengklik dropdown combobox. Jika total lebar setiap kolom lebih dari ListWidth, maka akan dimunculkan horisontal scrollbar, seperti 220pt.
  • BoundColumn : indeks kolom yang akan dijadikan nilai bagi properti Value (base 1 -> kolom ke-1 mendapat nomor indeks kolom 1). Nilai 0 berarti menampilkan nilai ListIndex atau indeks baris item (base 0).
  • TextColumn : indeks kolom yang akan dijadikan nilai bagi properti Text (base 1 dan defaultnya -1 yang berarti sama dengan BoundColumn). Nilai 0 berarti menampilkan nilai ListIndex atau indeks baris item (base 0).
Properti LinkedCell (jika digunakan) hanya bisa mengambil sebuah nilai yang dimiliki oleh properti Value yang terikat dengan kolom yang ditentukan pada properti BoundColumn. Sedangkan jumlah kolom dalam list ada lebih dari satu, maka sangat besar kemungkinan akan menggunakan script VBA untuk mendapatkan nilai dari kolom-kolom yang ada. Beberapa properti yang bermanfaat dalam pengambilan nilai dari kolom-kolom yang ada dalam list sebuah combobox antara lain adalah :
  • ListIndex : indeks baris list yang terpilih dengan nilai -1 yang berarti tidak ada yang terpilih dan nilai 0 sebagai item di baris pertama dalam list (base 0 -> item ke-1 diberi indeks bernilai 0).
  • Text : nilai yang ditampilkan oleh combobox yang berasal dari indeks kolom yang ditentukan pada properti TextColumn (base 1 -> kolom ke-1 dalam list diberi indeks kolom bernilai 1)
  • Value : nilai yang disimpan oleh combobox yang berasal dari indeks kolom yang ditentukan pada properti BoundColumn (base 1).
  • Column( idxcol ) : merujuk pada indeks kolom ke-idxcol (base 0), seperti Column(1) merujuk ke indeks kolom 1 yang berarti merujuk pada kolom ke-2 dalam list.
  • List( idxrow , idxcol ) : merujuk pada baris item dengan indeks baris ke-idxrow (base 0) dan kolom dengan indeks kolom ke-idxcol (base 0). Nilai idxrow pada baris terpilih adalah sebesar nilai properti ListIndex.
Pada saat user memilih sebuah item dari list, maka event yang bekerja adalah event Change. Jadi, jika diharapkan agar setiap user mengganti pilihan akan terjadi suatu proses tertentu seperti penulisan nilai-nilai ke suatu lokasi target, maka event change bisa diisi dengan script VBA tentang alur proses tersebut. Event Change milik combobox dapat dibuat dengan melakukan double click pada object control ketika dalam keadaan Design Mode. Gambar berikut ini adalah cuplikan dari sheet bernama list_fill_range yang menjadi contoh combobox dengan multiple column dan disertai dengan proses penulisan nilai ke suatu range.
Pada gambar, properti ListFillRange diisi dengan A2:C5 dengan jumlah kolom yang ditampilkan adalah 3 (isi ColumnCount) diisi 3. Jadi, sumber data list adalah range A2:C5 (3 kolom) ditampilkan dalam list sebanyak 3 kolom juga (ditampilkan seluruhnya). Properti LinkedCell juga digunakan dengan merujuk ke range B30 yang akan mengambil nilai di kolom ke-2 karena isi properti BoundColumn adalah 2 yang berarti properti Value akan mengambil nilai yang ada di kolom ke-2.

Pemanfaatan event Change milik combobox adalah untuk menulis beberapa informasi tentang nilai-nilai properti tertentu dari item yang terpilih, seperti properti ListIndex yang ditulis pada cell B33, Text pada cell B34 yang nilainya berasal dari kolom ke-1 berdasar isi properti TextColumn yang bernilai 1, Value yang nilainya berasal dari kolom ke-2 dan menghasilkan nilai yang sama dengan cell B30 yang diisi oleh properti LinkedCell. Juga nilai dari kolom ke-3 yang diambil dari list combobox menggunakan properti Column dengan idxcol bernilai 2 (cell B36) atau dengan properti List dengan idxrow senilai dengan nilai properti ListIndex (karena bagian idxrow dikosongkan) dan idxcol bernilai 2 (cell B37).

Prosedur Sub pada event change combobox tersebut berbunyi sebagai berikut :
Private Sub cboProd2_Change()
    'tulis informasi tentang data terpilih
    Range("b33").Value = cboProd2.ListIndex     'ListIndex
    Range("b34").Value = cboProd2.Text          'Text
    Range("b35").Value = cboProd2.Value         'Value
    Range("b36").Value = cboProd2.Column(2)     'Column indeks 2 [base 0]=kolom ke-3
    Range("b37").Value = cboProd2.List(, 2)     'List indeks kolom 2 [base 0]=kolom ke-3
End Sub


ComboBox pada sebuah UserForm

ActiveX Control memang lebih sering digunakan dalam UserForm yang tampak lebih cantik. ComboBox dalam sebuah UserForm juga bisa diisi dengan suatu data yang disimpan pada suatu area range secara mudah melalui pemanfaatan properti RowSource. Properti RowSource pada combobox di dalam UserForm setara dengan properti ListFillRange pada ComboBox yang diletakkan dalam sebuah worksheet. Properti LinkedCell di combobox dalam worksheet setara dengan properti ControlSource pada combobox di dalam sebuah UserForm.

Misalkan dibuat sebuah UserForm bernama frmNomor1 yang diberi combobox dengan nama cboProd. Pada cboProd, diatur dengan properti :
  • RowSource : berisi teks berbunyi list_fill_range!A2:C5
  • ColumnCount : berisi 3
  • ColumnHeads : TRUE
  • BoundColumn : berisi 2
  • ControlSource : berisi teks berbunyi list_fill_range!B57
  • TextColumn : berisi 1
Saat userform ditampilkan, maka cboProd akan berisi daftar yang bersumber dari sheet bernama list_fill_range pada area range A2:C5. Ketika user mengganti pilihan, maka cell B57 di sheet list_fill_range akan terisi dengan nilai dari kolom ke-2 dari list setelah combobox tidak lagi dalam keadaan aktif (kursor telah berpindah ke control lainnya). Hal ini diakibatkan oleh pengaturan properti ControlSource yang merujuk ke range di sheet tersebut. Sedangkan nilai yang diambil oleh ControlSource berasal dari properti Value yang diatur mengikuti isi properti BoundColumn yang merujuk pada kolom ke-2 dari list.

Event change pada cboProd bisa dimanfaatkan untuk menulis ke suatu range ataupun ke control lain saat user mengubah pilihan. Misalkan, saat user mengubah pilihan maka akan terjadi proses penulisan ke range tertentu seperti contoh prosedur sub pada event change cboProd berikut :
Private Sub cboProd_Change()
    'tulis informasi tentang data terpilih
   
    '>> ke worksheet 'Sheet1 (list_fill_range)'
    Sheet1.Range("b61").Value = cboProd.ListIndex   'ListIndex
    Sheet1.Range("b62").Value = cboProd.Text        'Text
    Sheet1.Range("b63").Value = cboProd.Value       'Value
    Sheet1.Range("b64").Value = cboProd.Column(2)   'Column indeks 2 [base 0]=kolom ke-3
    Sheet1.Range("b65").Value = cboProd.List(, 2)   'List indeks kolom 2 [base 0]=kolom ke-3

End Sub

Properti ControlSource juga dimiliki oleh control lain seperti TextBox. Misalnya di frmNomor1 tersebut juga ditambahkan 2 buah textbox. Textbox pertama diberi nama txtBound1 untuk terikat dengan range B57 (yang diisi oleh ControlSource milik combobox) dan textbox kedua diberi nama txtListIndex1 yang terikat dengan range B61. Isi properti ControlSource pada textbox txtBound1 berbunyi list_fill_range!B57 dan pada textbox txtListIndex1 berbunyi list_fill_range!B61. Setiapkali ada perubahan pada cell B57 dan B61, maka textbox juga akan berubah isinya ketika terjadi pembaruan tampilan frmNomor1. Pembaruan tampilan frmNomor1 bisa dipicu dengan mengganti control yang aktif melalui methods SetFocus. Jadi, pada event change milik cboProd juga bisa disertakan proses pembaruan tampilan ini dengan menambahkan baris-baris script berikut yang diletakkan pada bagian tepat sebelum End Sub setelah baris terakhir penulisan yang sudah ada.
    '>> supaya textbox control yang menggunakan properti ControlSource terupdate
    txtBound1.SetFocus      'salah satu control di-set focus
    'jika ingin dikembalikan ke combobox cboProd, maka set focus ke cboprod
    cboProd.SetFocus


Penulisan item terpilih ke control yang ada dalam userform juga bisa dilakukan dengan script VBA dan tanpa properti ControlSource milik control yang menjadi target. Misalnya pada frmNomor1 diberi textbox berikut :
  • txtListIndex : diisi dengan nilai properti ListIndex dari cboProd
  • txtValue : diisi dengan nilai yang disimpan oleh properti Value milik cboProd
  • txtText : diisi dengan nilai yang disimpan oleh properti Text milik cboProd
  • txtCol2 : diisi dengan nilai yang diambil dari kolom ke-3 list yang berindeks kolom senilai 2
maka pada event change milik cboProd bisa tambahkan script penulisan tersebut yang berbunyi :
    '>> ke TextBox di frame fraScript dalam userform frmNomor1
    txtListIndex.Text = cboProd.ListIndex   'ListIndex
    txtValue.Text = cboProd.Value           'Value -> tergantung BoundColumn
    txtText.Text = cboProd.Text             'Text  -> tergantung TextColumn
   
    'mengambil nilai dari kolom tertentu bisa dengan
    'properti Column(indeks kolom) atau properti List( nilai list index , indeks kolom )
    'seperti :
    txtCol2.Text = cboProd.Column(2)        'Column(2) -> column(0) adalah kolom ke-1
    'atau
    txtCol2.Text = cboProd.List(, 2)        'List(,2) -> column(0) adalah kolom ke-1


Berikut ini adalah cuplikan gambar bentuk userform bernama frmNomor1 :
Contoh tampilan hasil penulisan yang dilakukan oleh proses yang ada dalam prosedur sub event change milik cboProd adalah :

Script lengkap dari prosedur sub event change milik cboProd berbunyi :
Private Sub cboProd_Change()
    'tulis informasi tentang data terpilih
   
    '>> ke worksheet 'Sheet1 (list_fill_range)'
    Sheet1.Range("b61").Value = cboProd.ListIndex   'ListIndex
    Sheet1.Range("b62").Value = cboProd.Text        'Text
    Sheet1.Range("b63").Value = cboProd.Value       'Value
    Sheet1.Range("b64").Value = cboProd.Column(2)   'Column indeks 2 [base 0]=kolom ke-3
    Sheet1.Range("b65").Value = cboProd.List(, 2)   'List indeks kolom 2 [base 0]=kolom ke-3
   
    '>> supaya textbox control yang menggunakan properti ControlSource terupdate
    txtBound1.SetFocus      'salah satu control di-set focus
    'jika ingin dikembalikan ke combobox cboProd, maka set focus ke cboprod
    cboProd.SetFocus
   
    '>> ke TextBox di frame fraScript dalam userform frmNomor1
    txtListIndex.Text = cboProd.ListIndex   'ListIndex
    txtValue.Text = cboProd.Value           'Value -> tergantung BoundColumn
    txtText.Text = cboProd.Text             'Text  -> tergantung TextColumn
   
    'mengambil nilai dari kolom tertentu bisa dengan
    'properti Column(indeks kolom) atau properti List( nilai list index , indeks kolom )
    'seperti :
    txtCol2.Text = cboProd.Column(2)        'Column(2) -> column(0) adalah kolom ke-1
    'atau
    txtCol2.Text = cboProd.List(, 2)        'List(,2) -> column(0) adalah kolom ke-1
End Sub


:)

Insya Allah pembahasan tentang combobox akan dilanjutkan pada coretan berikutnya. Pembahasan combobox yang akan dibahas berikutnya antara lain tentang pengisian list dengan script VBA memanfaatkan methods AddItem maupun properti List yang diletakkan pada prosedur sub event initialize userform. Juga dibahas tentang methods Clear untuk menghapus seluruh isi list combobox. Proses pengubahan nilai suatu item dalam list, menghapus sebuah item, menambahkan sebuah item di baris baru ataupun disisipkan pada baris tertentu juga akan dibahas disana. Dampak pengubahan isi list combobox yang memicu dijalankannya event change beserta salah satu cara menghindarinya akan disertakan pada pembahasan tersebut.




15 komentar:

  1. Thank you Mr Kid yg selalu memberikan penjelasan super lengkap

    BalasHapus
  2. Mr Kid,
    Terima kasih atas pencerahannya.
    Ada satu pertanyaan yang masih menggelitik, mengapa Column Idx dan List Idx dimulai dari 0 (base 0) tetapi TextColumn dimulai dari 1(satu)

    BalasHapus
    Balasan
    1. Oh iya, di coretan belum ada penjelasan tentang penyebab base 1 pada BoundColumn dan TextColumn ya...
      Saya tambahkan hal ini di coretan ya...

      Jadi, BoundColumn dan TextColumn bernilai 0 akan menampilkan nilai yang disimpan oleh properti ListIndex. BoundColumn dan TextColumn adalah rambu-rambu dari user bagi si object dalam melakukan sesuatu. Sedangkan ListIndex, Column, List adalah upaya user untuk mengakses atau menggali informasi dari kegiatan rutin si object. BoundColumn dan TextColumn dilihat dari sisi user. ListIndex, List, Column dilihat dari sisi struktur yang ditata oleh si object itu sendiri.

      Sepertinya bisa agak jelas perbedaan fungsional antara BoundColumn TextColumn dengan properti ListIndex,List, dan Column.

      :)

      Hapus
  3. Mr Kid, Trims banyak...
    membantu banget, ada g' mas kompilasi dari semua postingan mas "belajar vba excel" dari ke 1 sampai ke 100 dan seterusnya yang bisa di download? he..he.. aku pengin banget, pliezzz

    BalasHapus
    Balasan
    1. Waduh, nulisnya pas sempet saja jeh...
      Jadi, sementara ini, bersabar dulu dengan per postingan saja ya...
      Mudah-mudahan kedepan ada jalan untuk bisa mengkompilasikannya.

      :)

      Hapus
  4. Mr. Kid. Terimakasih banyak informasinya.
    bisakah dihubingan via telepon, saya belajar, tapi saya gak tahu harus belajar kemana
    email saya. syamsudin_06@yahoo.co.id

    BalasHapus
  5. mr. kid boleh minta bantuannya , saya mau buat input data tabel di userform isi tabel terdapat 4 kolom ( no., nama barang , satuan , harga ) jadi tiap lis / baris mengisi ke cell yang sudah di tentukan . saya bingung harus menggunakan kontrol apa untuk membuat tabel input di userform , pakai listbox / listview kbanyakan hanya menampilkan data dr sheet dan inputnya via text box

    mohon informasi bantuannya untuk memecahkan masalah vba excel
    ini kontak saya :
    email : dediiskandar425@gmail.com
    pin bb : 5C62357C

    BalasHapus
    Balasan
    1. Hai Dedi,

      Entry data pada sebuah grid di dalam Excel Userform memang tidak mudah karena tidak ada control yang khusus untuk hal itu selain Office Spreadsheet. Office spreadsheet control adalah worksheet yang berupa sebuah control, sehingga bisa diletakkan disebuah userform. Control ini berisi worksheet, jadi sama saja dengan Anda menggunakan sebuah worksheet. Pengaturan batas jumlah kolom atau baris dan batasan yang bisa diisi kedalam sebuah cells nya adalah serumit Anda membatasi sebuah cells.

      Flexgrid adalah grid yang menyediakan fasilitas untuk mengubah isi sebuah cells dalam control tersebut. Tapi, entry datanya tidak langsung ke dalam cells tersebut. Biasanya entry data menggunakan textbox yang diletakkan tepat dicells flexgrid yang akan diubah isinya. Di Excel Userform, textbox harus diletakkan pada sebuah frame control.
      Kendala lainnya adalah harus ter-install-nya library control flexgrid di komputer yang akan menggunakannya. Apalagi bila user menggunakan office 64bit, tentu saja tidak bisa menggunakan flexgrid yang hanya punya 32bit library. Penggunaan listview juga demikian. Isu bit office akan menjadi pembatasnya.

      Ada baiknya langsung menggunakan worksheet tanpa userform saat meng-entry data. Tampilan tombol ini dan itu bisa dipasang dalam worksheet.

      Regards,
      Kid

      Hapus
  6. Yth Mr.Kid. Mohon ijin tanya. Newbie nih. Saya edit ribbon untuk cetak data dinamis. Di ribbon ada combobox1 untuk pilihan halaman, combobox2 untuk nomor peserta awal dan combobox3 untuk nomor urut terakhir cetak. Lalu ada icon quick print. Gimana ya supaya bisa nyetak dinamis dari ribbon dengan kriteria halaman. Gmn. Saya coba Kode VBA dan Custom UI-nya tp blm pas kayaknya. File tak sertakan nih. Mks

    BalasHapus
  7. Assalamualaikum Mr.
    Saya baru belajar vba. Sy buat form, isinya kelas, nama, pembayaran tanggal. Kelas sy buat combobox dgn mengisi rowsource berupa name range. Yg ingin sy tanyakan, bagaimana cmbbox nama bisa otomatis berisi nama sesuai dgn cmbbox kelas, dapatkah rowsource cmbbox nama, saya isi hasil atau value dari cmbbox kelas, formulany bagaimana. Terima kasih

    BalasHapus
    Balasan
    1. Diposting ke milis Belajar-Excel@yahoogroups.com ya

      Hapus
  8. Komentar ini telah dihapus oleh pengarang.

    BalasHapus
  9. Assalamu'alaikum
    Gan untuk penggunaan LinkedCell pada properti ListBox yang rangenya berada di sheet yang berbeda dari sheet dimana Listbox berada kok gak bisa ya walaupun sudah ditambah nama sheetnya ( contoh : LinkedCell : Sheet2!$A$1 )

    BalasHapus
    Balasan
    1. Wa'alaikumussalam wr wb

      Hai Sarah,

      Untuk LinkedCells (ketika object di dalam worksheet) atau ControlSource (ketika object di dalam userform), diisi dengan format : [nama workbook]'nama sheet'!alamatAtauNamaRange

      Setelah di-input dengan format tersebut, Excel akan menampilkan hasil inputan di properti tadi adalah tanpa nama workbook.

      Format tersebut bisa didapatkan dengan formula dalam sebuah cells :
      =Cells( "address", pilih sebuah cells lokasi yang diinginkan )

      Wassalamu'alaikum wr wb
      Kid


      Hapus