TL;DR
File Excel dibaca di Python pakai fungsi pandas.read_excel, yang butuh library openpyxl buat format .xlsx. Buat file dengan banyak sheet, isi parameter sheet_name dengan nama sheet, daftar nama, atau None supaya semua sheet kebaca sekaligus jadi dictionary. Jebakan yang paling sering muncul: kode nol di depan hilang, sel gabungan jadi kosong, dan tanggal kebaca sebagai angka, dan ketiganya bisa dicegah lewat parameter dtype dan converters.
File Excel dibaca di Python pakai satu fungsi: pandas.read_excel.
Satu baris kode, selesai. Masalahnya bukan di situ. Masalahnya file Excel yang beredar di kantor Indonesia jarang rapi.
Ada judul laporan tiga baris di atas header. Ada sel gabungan. Ada kode produk yang diawali nol. Ada kolom tanggal yang isinya campur teks dan angka.
Semua itu bikin read_excel ngasih hasil yang keliatan benar tapi angkanya meleset. Di bawah ini cara bacanya dengan benar, plus enam jebakan yang paling sering nyusahin.
Install pandas dan openpyxl, lalu panggil pd.read_excel dengan path filenya. pandas nggak bisa buka file Excel sendirian, dia butuh library pembaca terpisah. Buat format .xlsx mesinnya openpyxl, buat format lama .xls mesinnya xlrd.
pip install pandas openpyxl
import pandas as pd
df = pd.read_excel("penjualan_toko_berkah.xlsx")
print(df.shape)
print(df.head())
Kalau muncul pesan error yang nyebut openpyxl, artinya library-nya belum terpasang. Install dulu di dalam virtual environment proyekmu.
Isi parameter sheet_name. Nilainya bisa nama sheet, nomor urut sheet, daftar beberapa sheet, atau None buat baca semuanya. Kalau isinya daftar atau None, hasilnya berupa dictionary dengan nama sheet sebagai kunci, bukan DataFrame tunggal.
# Satu sheet berdasarkan nama
df = pd.read_excel("laporan.xlsx", sheet_name="Januari")
# Sheet kedua berdasarkan posisi (mulai dari 0)
df = pd.read_excel("laporan.xlsx", sheet_name=1)
# Beberapa sheet sekaligus
sheets = pd.read_excel("laporan.xlsx", sheet_name=["Januari", "Februari"])
print(sheets["Februari"].head())
# Semua sheet
semua = pd.read_excel("laporan.xlsx", sheet_name=None)
print(list(semua.keys()))
Buat gabungin semua sheet jadi satu tabel, pakai pd.concat sambil nyimpen nama sheet-nya jadi kolom baru:
gabungan = pd.concat(
[df.assign(bulan=nama) for nama, df in semua.items()],
ignore_index=True,
)
print(gabungan["bulan"].value_counts())
Kolom bulan itu penyelamat. Tanpa itu, begitu digabung kamu nggak bisa lagi tau baris mana datang dari sheet mana.
Pakai pd.ExcelFile. Objek ini buka filenya sekali, jadi kamu bisa intip nama sheet lalu ambil yang kamu butuh tanpa mengurai ulang seluruh file.
xl = pd.ExcelFile("laporan.xlsx")
print(xl.sheet_names)
# ['Ringkasan', 'Januari', 'Februari', 'Maret', 'Catatan']
df = xl.parse("Februari")
Buat file besar yang kamu baca berkali-kali, cara ini jauh lebih cepat dari manggil read_excel berulang.
| Parameter | Fungsi | Contoh |
|---|---|---|
sheet_name | Pilih sheet | sheet_name="Januari" |
skiprows | Lewati baris judul di atas header | skiprows=3 |
header | Baris mana yang jadi nama kolom | header=2 |
usecols | Ambil kolom tertentu saja | usecols="A:F" |
dtype | Paksa tipe data kolom | dtype={"kode": str} |
na_values | Nilai yang dianggap kosong | na_values=["-", "n/a"] |
nrows | Batasi jumlah baris | nrows=100 |
parse_dates | Ubah kolom jadi tanggal | parse_dates=["tanggal"] |
Daftar lengkapnya ada di dokumentasi resmi pandas.read_excel.
Kode produk 007 kebaca jadi 7. NIK yang diawali nol ikut kepotong. Ini jebakan yang paling mahal, soalnya hasil join-nya bakal kosong tanpa pesan error.
df = pd.read_excel("produk.xlsx", dtype={"kode_produk": str, "nik": str})
Kalau baris 1 sampai 3 isinya judul dan tanggal cetak, pandas bakal ngira baris 1 itu nama kolom. Hasilnya kolom bernama Unnamed: 0 di mana-mana.
df = pd.read_excel("laporan.xlsx", skiprows=3)
print(df.columns.tolist())
Sel gabungan di Excel cuma nyimpen nilai di sel kiri atas. Sisanya kosong. Di pandas, itu jadi NaN yang menyebar ke bawah.
df["cabang"] = df["cabang"].ffill()
Perintah ffill nyalin nilai terakhir yang ada ke baris kosong di bawahnya. Cek dulu hasilnya, soalnya cara ini salah kalau kekosongannya beneran berarti nol.
Kolom yang isinya "1.250.000" dengan titik pemisah ribuan bakal kebaca sebagai teks. Hitungan apa pun di kolom itu bakal error atau hasilnya aneh.
df["omzet"] = (
df["omzet"].astype(str)
.str.replace(".", "", regex=False)
.str.replace(",", ".", regex=False)
)
df["omzet"] = pd.to_numeric(df["omzet"], errors="coerce")
print(df["omzet"].isna().sum())
Baris terakhir wajib. Itu ngasih tau berapa nilai yang gagal dikonversi dan berubah jadi kosong.
Excel nyimpan tanggal sebagai angka hari sejak 1899. Kalau formatnya kacau, kamu bakal lihat angka 45678 di kolom tanggal.
df["tanggal"] = pd.to_datetime(
df["tanggal_serial"], unit="D", origin="1899-12-30"
)
Angka 1899-12-30 itu bukan salah ketik. Excel nganggap tahun 1900 punya 29 Februari, padahal nggak, jadi titik awalnya digeser sehari.
pandas baca hasil hitungan terakhir yang tersimpan di file, bukan teks rumusnya. Kalau file dibikin oleh sistem lain yang nggak nyimpen hasil hitungan, sel berumus kebaca kosong. Solusinya buka file itu di Excel lalu simpan ulang.
Aku pernah gabungin 12 sheet laporan bulanan toko_berkah jadi satu tabel. Total baris di file aslinya 14.302.
Setelah digabung dan di-join sama tabel master produk, yang cocok cuma 12.455 baris. Ada 1.847 baris yang nggak nemu pasangan, sekitar 12,9 persen dari total.
Penyebabnya kode produk. Di file master, kode disimpan sebagai teks dengan format lima digit kayak "00841". Di file transaksi, kolom yang sama kebaca sebagai angka jadi "841".
Perbaikannya satu parameter:
trx = pd.read_excel("transaksi.xlsx", sheet_name=None,
dtype={"kode_produk": str})
master = pd.read_excel("master.xlsx", dtype={"kode_produk": str})
Setelah itu semua 14.302 baris cocok. Kalau aku nggak ngecek jumlah baris sebelum dan sesudah join, laporan omzet bulan itu bakal kurang sekitar Rp 214 juta tanpa ada yang sadar.
Kebiasaan yang aku pasang sejak itu: selalu cetak df.shape sebelum dan sesudah setiap operasi gabung.
df.shape, bandingkan dengan yang kelihatan di Excel.df.dtypes. Kolom kode harus object, kolom uang harus angka.df.isna().sum().value_counts(). Di situ ketahuan kalau ada "Depok" dan "depok" yang dianggap beda.df.tail(). Baris total di ujung laporan sering kebawa jadi data.Kalau langkah pembersihannya lebih cepat dikerjakan di spreadsheet, fungsi kayak TEXT buat jaga format kode dan IFERROR buat nutup nilai error bisa dipakai sebelum filenya dibaca Python. Pengecekan data quality di awal selalu lebih murah dari nambal di akhir.
Karena pandas butuh library terpisah buat baca Excel, dan openpyxl nggak terpasang otomatis. Jalankan pip install openpyxl. Buat format lama .xls, install xlrd.
Isi sheet_name dengan None. Hasilnya dictionary dengan nama sheet sebagai kunci. Gabungkan pakai pd.concat kalau strukturnya sama.
Karena pandas nebak kolom itu angka, dan 007 sama dengan 7. Cegah pakai dtype={"kode_produk": str} waktu baca filenya.
Sebagai hasil hitungan terakhir yang tersimpan di file, bukan teks rumusnya. Kalau file dibikin sistem lain yang nggak nyimpen hasil, selnya kebaca kosong.
Buka sekali pakai pd.ExcelFile lalu ambil sheet dari objek itu. Batasi kolom lewat usecols. Buat file di atas 50 MB, ubah sekali jadi Parquet atau CSV.
Tiga kebiasaan yang nyelametin paling banyak waktu: sebut dtype buat semua kolom kode, cek shape sebelum dan sesudah join, dan lihat tail() buat nangkap baris total yang kebawa.
Setelah datamu bersih, lanjut ke visualisasi lewat 10 plot Seaborn yang paling kepakai atau tutorial Matplotlib bahasa Indonesia.
Ambil satu file Excel dari kerjaanmu sekarang, baca pakai read_excel, lalu jalankan lima langkah checklist di atas. Kalau ada satu yang mengagetkan, berarti checklist-nya sudah bekerja.
Mau praktek langsung? Mulai latihan SQL gratis
Latihan interaktif, langsung di browser.
Kolom datetime nyimpen tanggal, jam, hari, semuanya nempel jadi satu. Accessor .dt di pandas ngeluarin tiap bagian jadi kolom sendiri buat dianalisa.
Nama toko ketik campur huruf besar-kecil, spasi nyasar di ujung, atau kode produk nempel jadi satu. Accessor .str di pandas ngerapiin semua itu tanpa loop.
Model machine learning cuma ngerti angka, bukan teks kayak merah atau biru. get_dummies ngubah kolom kategori jadi kolom 0/1 dalam satu baris kode.