02_reading_excel.py
Python/Excel/session_02_reading/02_reading_excel.py
"""
Session 2: Reading Excel Files - Comprehensive Examples
=======================================================
This script demonstrates advanced techniques for reading Excel files
with various structures and requirements.
"""
import pandas as pd
import numpy as np
from openpyxl import load_workbook
from pathlib import Path
import sys
print("=" * 80)
print("Session 2: Reading Excel Files - Comprehensive Techniques")
print("=" * 80)
print()
# Create sample data directory
sample_dir = Path(__file__).parent / 'sample_files'
sample_dir.mkdir(exist_ok=True)
# ==============================================================================
# 1. CREATE VARIOUS SAMPLE FILES FOR DEMONSTRATION
# ==============================================================================
print("1. CREATING SAMPLE EXCEL FILES WITH DIFFERENT STRUCTURES")
print("-" * 80)
# Sample 1: Simple dataset
df_simple = pd.DataFrame({
'Name': ['Alice', 'Bob', 'Charlie', 'Diana', 'Eve'],
'Age': [25, 30, 35, 28, 32],
'Department': ['Sales', 'IT', 'Sales', 'HR', 'IT'],
'Salary': [60000, 75000, 65000, 58000, 72000]
})
simple_file = sample_dir / 'simple_data.xlsx'
df_simple.to_excel(simple_file, index=False)
print(f"✓ Created: {simple_file}")
# Sample 2: Multi-sheet workbook
df_sales = pd.DataFrame({
'Product': ['A', 'B', 'C', 'D'],
'Q1': [100, 150, 200, 175],
'Q2': [110, 160, 210, 180],
'Q3': [120, 170, 220, 190],
'Q4': [130, 180, 230, 200]
})
df_expenses = pd.DataFrame({
'Category': ['Rent', 'Utilities', 'Salaries', 'Marketing'],
'Amount': [5000, 1500, 25000, 3000]
})
multi_sheet_file = sample_dir / 'multi_sheet.xlsx'
with pd.ExcelWriter(multi_sheet_file) as writer:
df_sales.to_excel(writer, sheet_name='Sales', index=False)
df_expenses.to_excel(writer, sheet_name='Expenses', index=False)
print(f"✓ Created: {multi_sheet_file}")
# Sample 3: File with headers in row 3
df_with_header_offset = pd.DataFrame({
'ID': range(1, 11),
'Product': [f'Product_{i}' for i in range(1, 11)],
'Price': np.random.uniform(10, 100, 10).round(2)
})
header_offset_file = sample_dir / 'header_offset.xlsx'
with pd.ExcelWriter(header_offset_file, engine='openpyxl') as writer:
# Write DataFrame starting from row 3
df_with_header_offset.to_excel(writer, sheet_name='Data',
startrow=2, index=False)
# Access the worksheet to add headers
worksheet = writer.sheets['Data']
worksheet.cell(1, 1, 'Company Sales Report')
worksheet.cell(2, 1, 'Generated: 2024')
print(f"✓ Created: {header_offset_file}")
print()
# ==============================================================================
# 2. BASIC READING TECHNIQUES
# ==============================================================================
print("2. BASIC READING TECHNIQUES")
print("-" * 80)
# Read simple file
df = pd.read_excel(simple_file)
print("Simple file read:")
print(df)
print()
# Get basic info
print("DataFrame Info:")
print(f"Shape: {df.shape}")
print(f"Columns: {df.columns.tolist()}")
print(f"Data types:\n{df.dtypes}")
print()
# ==============================================================================
# 3. READING SPECIFIC SHEETS
# ==============================================================================
print("3. READING SPECIFIC SHEETS")
print("-" * 80)
# Read specific sheet by name
df_sales_read = pd.read_excel(multi_sheet_file, sheet_name='Sales')
print("Sales sheet:")
print(df_sales_read)
print()
# Read specific sheet by index
df_expenses_read = pd.read_excel(multi_sheet_file, sheet_name=1)
print("Expenses sheet (by index):")
print(df_expenses_read)
print()
# Read all sheets
all_sheets = pd.read_excel(multi_sheet_file, sheet_name=None)
print(f"All sheets: {list(all_sheets.keys())}")
for sheet_name, df_sheet in all_sheets.items():
print(f"\n{sheet_name}:")
print(df_sheet.head())
print()
# ==============================================================================
# 4. READING SPECIFIC ROWS AND COLUMNS
# ==============================================================================
print("4. READING SPECIFIC ROWS AND COLUMNS")
print("-" * 80)
# Skip rows
df_skip = pd.read_excel(simple_file, skiprows=2)
print("Skip first 2 data rows:")
print(df_skip)
print()
# Read specific columns
df_cols = pd.read_excel(simple_file, usecols=['Name', 'Salary'])
print("Read only Name and Salary columns:")
print(df_cols)
print()
# Read specific columns by index
df_cols_idx = pd.read_excel(simple_file, usecols=[0, 3])
print("Read columns 0 and 3:")
print(df_cols_idx)
print()
# Limit number of rows
df_nrows = pd.read_excel(simple_file, nrows=3)
print("Read only first 3 rows:")
print(df_nrows)
print()
# ==============================================================================
# 5. HANDLING HEADERS
# ==============================================================================
print("5. HANDLING HEADERS")
print("-" * 80)
# Read with header in different row
df_offset = pd.read_excel(header_offset_file, sheet_name='Data', header=2)
print("Read with header in row 3:")
print(df_offset)
print()
# Read without headers
df_no_header = pd.read_excel(simple_file, header=None)
print("Read without using headers:")
print(df_no_header.head())
print()
# Read without headers and assign custom names
df_custom_names = pd.read_excel(simple_file, header=None,
names=['Col1', 'Col2', 'Col3', 'Col4'],
skiprows=1)
print("Custom column names:")
print(df_custom_names.head())
print()
# ==============================================================================
# 6. DATA TYPE HANDLING
# ==============================================================================
print("6. DATA TYPE HANDLING")
print("-" * 80)
# Create file with mixed types
df_mixed = pd.DataFrame({
'ID': ['001', '002', '003', '004'],
'Name': ['Alice', 'Bob', 'Charlie', 'Diana'],
'Date': pd.date_range('2024-01-01', periods=4),
'Score': [95.5, 87.3, 92.1, 88.9],
'Active': [True, True, False, True]
})
mixed_file = sample_dir / 'mixed_types.xlsx'
df_mixed.to_excel(mixed_file, index=False)
# Read with automatic type inference
df_auto = pd.read_excel(mixed_file)
print("Automatic type inference:")
print(df_auto.dtypes)
print()
# Read with explicit types
df_explicit = pd.read_excel(mixed_file, dtype={
'ID': str,
'Name': str,
'Score': float,
'Active': bool
})
print("Explicit type specification:")
print(df_explicit.dtypes)
print()
# ==============================================================================
# 7. READING WITH OPENPYXL
# ==============================================================================
print("7. READING WITH OPENPYXL")
print("-" * 80)
# Load workbook
wb = load_workbook(simple_file)
print(f"Workbook sheets: {wb.sheetnames}")
print()
# Access sheet
ws = wb.active
print(f"Active sheet: {ws.title}")
print(f"Dimensions: {ws.dimensions}")
print()
# Read specific cells
print("Reading specific cells:")
print(f"A1 (header): {ws['A1'].value}")
print(f"A2 (first data): {ws['A2'].value}")
print(f"D2 (salary): {ws['D2'].value}")
print()
# Iterate through rows
print("First 3 rows:")
for idx, row in enumerate(ws.iter_rows(min_row=1, max_row=3, values_only=True), 1):
print(f"Row {idx}: {row}")
print()
# Read specific range
print("Reading range A1:C3:")
for row in ws['A1:C3']:
values = [cell.value for cell in row]
print(values)
print()
# ==============================================================================
# 8. COMBINING MULTIPLE SHEETS
# ==============================================================================
print("8. COMBINING MULTIPLE SHEETS")
print("-" * 80)
# Create multiple sheet files
monthly_data = {}
for month in ['January', 'February', 'March']:
monthly_data[month] = pd.DataFrame({
'Product': ['A', 'B', 'C'],
'Sales': np.random.randint(100, 500, 3),
'Month': month
})
monthly_file = sample_dir / 'monthly_sales.xlsx'
with pd.ExcelWriter(monthly_file) as writer:
for month, df_month in monthly_data.items():
df_month.to_excel(writer, sheet_name=month, index=False)
print(f"✓ Created monthly sales file: {monthly_file}")
print()
# Read and combine all sheets
all_months = pd.read_excel(monthly_file, sheet_name=None)
combined_df = pd.concat(all_months.values(), ignore_index=True)
print("Combined data from all months:")
print(combined_df)
print()
# ==============================================================================
# 9. ERROR HANDLING
# ==============================================================================
print("9. ERROR HANDLING BEST PRACTICES")
print("-" * 80)
def safe_read_excel(file_path, **kwargs):
"""Safely read Excel file with error handling"""
try:
file_path = Path(file_path)
if not file_path.exists():
print(f"✗ Error: File not found: {file_path}")
return None
if not str(file_path).endswith(('.xlsx', '.xls', '.xlsm')):
print(f"✗ Error: Invalid file format")
return None
df = pd.read_excel(file_path, **kwargs)
if df.empty:
print(f"⚠ Warning: File is empty")
return None
print(f"✓ Successfully read: {file_path.name}")
return df
except PermissionError:
print(f"✗ Error: Permission denied. File may be open in Excel.")
return None
except ValueError as e:
print(f"✗ ValueError: {e}")
return None
except Exception as e:
print(f"✗ Unexpected error: {type(e).__name__}: {e}")
return None
# Test error handling
print("Testing error handling:")
df = safe_read_excel(simple_file)
if df is not None:
print(f"DataFrame shape: {df.shape}")
print()
df = safe_read_excel('non_existent.xlsx')
print()
df = safe_read_excel(simple_file, sheet_name='NonExistentSheet')
print()
# ==============================================================================
# 10. PERFORMANCE COMPARISON
# ==============================================================================
print("10. PERFORMANCE COMPARISON")
print("-" * 80)
# Create larger dataset
large_data = pd.DataFrame({
'ID': range(1, 1001),
'Name': [f'Person_{i}' for i in range(1, 1001)],
'Value': np.random.randn(1000)
})
large_file = sample_dir / 'large_dataset.xlsx'
large_data.to_excel(large_file, index=False)
import time
# Test pandas
start = time.time()
df_pandas = pd.read_excel(large_file)
pandas_time = time.time() - start
# Test openpyxl read_only
start = time.time()
wb = load_workbook(large_file, read_only=True)
ws = wb.active
data_list = [[cell.value for cell in row] for row in ws.iter_rows()]
df_openpyxl = pd.DataFrame(data_list[1:], columns=data_list[0])
wb.close()
openpyxl_time = time.time() - start
print(f"Pandas read time: {pandas_time:.4f} seconds")
print(f"Openpyxl read time: {openpyxl_time:.4f} seconds")
print()
if pandas_time < openpyxl_time:
print(f"✓ Pandas is {openpyxl_time/pandas_time:.2f}x faster")
else:
print(f"✓ Openpyxl is {pandas_time/openpyxl_time:.2f}x faster")
print()
# ==============================================================================
# SUMMARY
# ==============================================================================
print("=" * 80)
print("SESSION 2 COMPLETE!")
print("=" * 80)
print()
print("What you learned:")
print("✓ Read single and multiple sheets")
print("✓ Read specific rows, columns, and ranges")
print("✓ Handle different data types")
print("✓ Work with headers and indices")
print("✓ Use both pandas and openpyxl effectively")
print("✓ Implement error handling")
print("✓ Compare performance of different methods")
print()
print("Files created:")
for file in sample_dir.glob('*.xlsx'):
print(f" - {file.name}")
print()
print("Next: Session 3 - Writing Excel Files")
print("=" * 80)
Articoli correlati
01_getting_started.py
01_getting_started.py — python source code from the Python learning materials (Python/01_beginner_level/01_getting_started.py).
Leggi l'articolo →02_core_syntax.py
02_core_syntax.py — python source code from the Python learning materials (Python/01_beginner_level/02_core_syntax.py).
Leggi l'articolo →03_control_flow.py
03_control_flow.py — python source code from the Python learning materials (Python/01_beginner_level/03_control_flow.py).
Leggi l'articolo →04_data_structures.py
04_data_structures.py — python source code from the Python learning materials (Python/01_beginner_level/04_data_structures.py).
Leggi l'articolo →05_functions.py
05_functions.py — python source code from the Python learning materials (Python/01_beginner_level/05_functions.py).
Leggi l'articolo →06_error_handling.py
06_error_handling.py — python source code from the Python learning materials (Python/01_beginner_level/06_error_handling.py).
Leggi l'articolo →