Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Analyze Excel spreadsheets, create pivot tables, generate charts, and perform data analysis. Use when analyzing Excel files, spreadsheets, tabular data, or .xlsx files.
.claude/skills/davila7-excel-analysis/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✗→✓ | ▲ Improved | 29% | 0% |
| case-14 | ✗→✓ | ▲ Improved | 148% | 0% |
| case-15 | ✓→✗ | ▼ Worse | 127% | 0% |
| case-02 | ✓→✓ | = Same ✓ | 76% | 0% |
| case-03 | ✓→✓ | = Same ✓ | 146% | 0% |
Read Excel files with pandas:
pythonimport pandas as pd # Read Excel file df = pd.read_excel("data.xlsx", sheet_name="Sheet1") # Display first few rows print(df.head()) # Basic statistics print(df.describe())
Process all sheets in a workbook:
pythonimport pandas as pd # Read all sheets excel_file = pd.ExcelFile("workbook.xlsx") for sheet_name in excel_file.sheet_names: df = pd.read_excel(excel_file, sheet_name=sheet_name) print(f"\n{sheet_name}:") print(df.head())
Perform common analysis tasks:
pythonimport pandas as pd df = pd.read_excel("sales.xlsx") # Group by and aggregate sales_by_region = df.groupby("region")["sales"].sum() print(sales_by_region) # Filter data high_sales = df[df["sales"] > 10000] # Calculate metrics df["profit_margin"] = (df["revenue"] - df["cost"]) / df["revenue"] # Sort by column df_sorted = df.sort_values("sales", ascending=False)
Write data to Excel with formatting:
pythonimport pandas as pd df = pd.DataFrame({ "Product": ["A", "B", "C"], "Sales": [100, 200, 150], "Profit": [20, 40, 30] }) # Write to Excel writer = pd.ExcelWriter("output.xlsx", engine="openpyxl") df.to_excel(writer, sheet_name="Sales", index=False) # Get worksheet for formatting worksheet = writer.sheets["Sales"] # Auto-adjust column widths for column in worksheet.columns: max_length = 0 column_letter = column[0].column_letter for cell in column: if len(str(cell.value)) > max_length: max_length = len(str(cell.value)) worksheet.column_dimensions[column_letter].width = max_length + 2 writer.close()
Create pivot tables programmatically:
pythonimport pandas as pd df = pd.read_excel("sales_data.xlsx") # Create pivot table pivot = pd.pivot_table( df, values="sales", index="region", columns="product", aggfunc="sum", fill_value=0 ) print(pivot) # Save pivot table pivot.to_excel("pivot_report.xlsx")
Generate charts from Excel data:
pythonimport pandas as pd import matplotlib.pyplot as plt df = pd.read_excel("data.xlsx") # Create bar chart df.plot(x="category", y="value", kind="bar") plt.title("Sales by Category") plt.xlabel("Category") plt.ylabel("Sales") plt.tight_layout() plt.savefig("chart.png") # Create pie chart df.set_index("category")["value"].plot(kind="pie", autopct="%1.1f%%") plt.title("Market Share") plt.ylabel("") plt.savefig("pie_chart.png")
Clean and prepare Excel data:
pythonimport pandas as pd df = pd.read_excel("messy_data.xlsx") # Remove duplicates df = df.drop_duplicates() # Handle missing values df = df.fillna(0) # or df.dropna() # Remove whitespace df["name"] = df["name"].str.strip() # Convert data types df["date"] = pd.to_datetime(df["date"]) df["amount"] = pd.to_numeric(df["amount"], errors="coerce") # Save cleaned data df.to_excel("cleaned_data.xlsx", index=False)
Combine multiple Excel files:
pythonimport pandas as pd # Read multiple files df1 = pd.read_excel("sales_q1.xlsx") df2 = pd.read_excel("sales_q2.xlsx") # Concatenate vertically combined = pd.concat([df1, df2], ignore_index=True) # Merge on common column customers = pd.read_excel("customers.xlsx") sales = pd.read_excel("sales.xlsx") merged = pd.merge(sales, customers, on="customer_id", how="left") merged.to_excel("merged_data.xlsx", index=False)
Apply conditional formatting and styles:
pythonimport pandas as pd from openpyxl import load_workbook from openpyxl.styles import PatternFill, Font # Create Excel file df = pd.DataFrame({ "Product": ["A", "B", "C"], "Sales": [100, 200, 150] }) df.to_excel("formatted.xlsx", index=False) # Load workbook for formatting wb = load_workbook("formatted.xlsx") ws = wb.active # Apply conditional formatting red_fill = PatternFill(start_color="FF0000", end_color="FF0000", fill_type="solid") green_fill = PatternFill(start_color="00FF00", end_color="00FF00", fill_type="solid") for row in range(2, len(df) + 2): cell = ws[f"B{row}"] if cell.value < 150: cell.fill = red_fill else: cell.fill = green_fill # Bold headers for cell in ws[1]: cell.font = Font(bold=True) wb.save("formatted.xlsx")
read_excel with usecols to read specific columns onlychunksize for very large filesengine='openpyxl' or engine='xlrd' based on file typedtype parameter to specify column types for faster reading| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | fail→pass | 15,193 | 11,900 | -22% | 1 | 1 | 0% | 2,911 | 3,768 | +29% | 0 | 0 | — |
case-02 | pass→pass | 7,124 | 4,931 | -31% | 1 | 1 | 0% | 1,449 | 2,554 | +76% | 0 | 0 | — |
case-03 | pass→pass | 5,205 | 4,012 | -23% | 1 | 1 | 0% | 937 | 2,303 | +146% | 0 | 0 | — |
case-04 | fail→fail | 5,168 | 3,020 | -42% | 1 | 1 | 0% | 986 | 2,115 | +115% | 0 | 0 | — |
case-05 | pass→pass | 6,637 | 13,899 | +109% | 1 | 1 | 0% | 1,163 | 2,452 | +111% | 0 | 0 | — |
case-06 | pass→pass | 4,168 | 2,877 | -31% | 1 | 1 | 0% | 626 | 2,025 | +223% | 0 | 0 | — |
case-07 | pass→pass | 4,632 | 3,456 | -25% | 1 | 1 | 0% | 735 | 2,214 | +201% | 0 | 0 | — |
case-08 | pass→pass | 4,154 | 3,156 | -24% | 1 | 1 | 0% | 830 | 2,013 | +143% | 0 | 0 | — |
case-09 | pass→pass | 5,075 | 3,049 | -40% | 1 | 1 | 0% | 992 | 2,101 | +112% | 0 | 0 | — |
case-10 | pass→pass | 4,856 | 3,661 | -25% | 1 | 1 | 0% | 934 | 2,290 | +145% | 0 | 0 | — |
case-11 | pass→pass | 3,151 | 2,026 | -36% | 1 | 1 | 0% | 442 | 1,830 | +314% | 0 | 0 | — |
case-12 | pass→pass | 2,956 | 2,149 | -27% | 1 | 1 | 0% | 453 | 1,843 | +307% | 0 | 0 | — |
case-13 | pass→pass | 3,441 | 2,419 | -30% | 1 | 1 | 0% | 613 | 1,946 | +217% | 0 | 0 | — |
case-14 | fail→pass | 4,844 | 3,783 | -22% | 1 | 1 | 0% | 940 | 2,331 | +148% | 0 | 0 | — |
case-15 | pass→fail | 5,455 | 3,943 | -28% | 1 | 1 | 0% | 1,040 | 2,364 | +127% | 0 | 0 | — |
case-16 | pass→pass | 3,050 | 2,185 | -28% | 1 | 1 | 0% | 430 | 1,921 | +347% | 0 | 0 | — |
case-17 | pass→pass | 5,556 | 4,077 | -27% | 1 | 1 | 0% | 1,027 | 2,285 | +122% | 0 | 0 | — |
case-18 | pass→pass | 4,206 | 2,831 | -33% | 1 | 1 | 0% | 807 | 2,075 | +157% | 0 | 0 | — |
case-19 | pass→pass | 2,012 | 1,607 | -20% | 1 | 1 | 0% | 285 | 1,763 | +519% | 0 | 0 | — |
case-20 | pass→pass | 1,240 | 2,002 | +61% | 1 | 1 | 0% | 198 | 1,729 | +773% | 0 | 0 | — |
case-21 | pass→pass | 6,117 | 5,270 | -14% | 1 | 1 | 0% | 1,032 | 2,558 | +148% | 0 | 0 | — |
case-22 | pass→pass | 9,755 | 8,363 | -14% | 1 | 1 | 0% | 1,937 | 3,013 | +56% | 0 | 0 | — |
case-23 | pass→pass | 7,593 | 6,332 | -17% | 1 | 1 | 0% | 1,386 | 2,659 | +92% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 23 cases were attempted. The headline lift of +4 percentage points is the difference between those two pass rates over the 23 comparable cases. 1 case got worse with the skill loaded, and it is included in that figure.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.