Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Create, edit, analyze, or convert Excel spreadsheets (.xlsx, .xlsm) where the workbook file is the primary deliverable. Use for formulas, formatting, financial models, multi-sheet workbooks, and tabular cleanup exported to Excel. Also applies to .csv/.tsv when the user wants spreadsheet output. Do NOT use for Word documents, HTML reports, standalone Python scripts, database pipelines, or Google Sheets API work.
.claude/skills/lingxling-xlsx/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-05 | ✗→✓ | ▲ Improved | 76% | 0% |
| case-06 | ✗→✓ | ▲ Improved | 91% | 0% |
| case-07 | ✗→✓ | ▲ Improved | 154% | 0% |
| case-11 | ✗→✓ | ▲ Improved | 131% | 0% |
| case-18 | ✓→✗ | ▼ Worse | 59% | 0% |
Unless otherwise stated by the user or existing template
A user may ask you to create, edit, or analyze the contents of an .xlsx file. You have different tools and workflows available for different tasks.
bashuv pip install openpyxl pandas
Optional — faster Excel reading across formats with pandas 2.2+:
bashuv pip install python-calamine
For untrusted workbook files, harden openpyxl against XML expansion attacks:
bashuv pip install defusedxml
See openpyxl security guidance.
LibreOffice required for formula recalculation: Assume LibreOffice is installed for recalculating formula values using scripts/recalc.py. The script configures LibreOffice on first run, including in sandboxed environments where Unix sockets are restricted (handled by scripts/office/soffice.py).
System dependencies (not installed via uv):
| Tool | Purpose | |------|---------| | soffice (LibreOffice 7.x+) | Evaluates Excel formulas via scripts/recalc.py | | gcc | Only when Unix domain sockets are blocked; compiles a one-time shim into ~/.cache/xlsx-skill/lo-shim/ | | gtimeout (macOS, optional) | GNU coreutils timeout for recalc timeout support on Darwin |
Verify LibreOffice is available: soffice --version
For data analysis, visualization, and basic operations, use pandas which provides powerful data manipulation capabilities:
pythonimport pandas as pd # Read Excel (.xlsx default engine: openpyxl) df = pd.read_excel('file.xlsx') # Default: first sheet all_sheets = pd.read_excel('file.xlsx', sheet_name=None) # All sheets as dict # Optional: calamine engine (pandas 2.2+) — faster, supports .xlsx/.xls/.xlsb/.xlsm/.ods # df = pd.read_excel('file.xlsx', engine='calamine') # Analyze df.head() # Preview data df.info() # Column info df.describe() # Statistics # Write Excel df.to_excel('output.xlsx', index=False)
Always use Excel formulas instead of calculating values in Python and hardcoding them. This ensures the spreadsheet remains dynamic and updateable.
python# Bad: Calculating in Python and hardcoding result total = df['Sales'].sum() sheet['B10'] = total # Hardcodes 5000 # Bad: Computing growth rate in Python growth = (df.iloc[-1]['Revenue'] - df.iloc[0]['Revenue']) / df.iloc[0]['Revenue'] sheet['C5'] = growth # Hardcodes 0.15 # Bad: Python calculation for average avg = sum(values) / len(values) sheet['D20'] = avg # Hardcodes 42.5
python# Good: Let Excel calculate the sum sheet['B10'] = '=SUM(B2:B9)' # Good: Growth rate as Excel formula sheet['C5'] = '=(C4-C2)/C2' # Good: Average using Excel function sheet['D20'] = '=AVERAGE(D2:D19)'
This applies to ALL calculations - totals, percentages, ratios, differences, etc. The spreadsheet should be able to recalculate when source data changes.
scripts/recalc.py scriptbash python skills/xlsx/scripts/recalc.py output.xlsx
status is errors_found, check error_summary for specific error types and locations#REF!: Invalid cell references#DIV/0!: Division by zero#VALUE!: Wrong data type in formula#NAME?: Unrecognized formula namepython# Using openpyxl for formulas and formatting from openpyxl import Workbook from openpyxl.styles import Font, PatternFill, Alignment wb = Workbook() sheet = wb.active # Add data sheet['A1'] = 'Hello' sheet['B1'] = 'World' sheet.append(['Row', 'of', 'data']) # Add formula sheet['B2'] = '=SUM(A1:A10)' # Formatting sheet['A1'].font = Font(bold=True, color='FF0000') sheet['A1'].fill = PatternFill('solid', start_color='FFFF00') sheet['A1'].alignment = Alignment(horizontal='center') # Column width sheet.column_dimensions['A'].width = 20 wb.save('output.xlsx')
python# Using openpyxl to preserve formulas and formatting from openpyxl import load_workbook # Load existing file wb = load_workbook('existing.xlsx') sheet = wb.active # or wb['SheetName'] for specific sheet # Working with multiple sheets for sheet_name in wb.sheetnames: sheet = wb[sheet_name] print(f"Sheet: {sheet_name}") # Modify cells sheet['A1'] = 'New Value' sheet.insert_rows(2) # Insert row at position 2 sheet.delete_cols(3) # Delete column 3 # Add new sheet new_sheet = wb.create_sheet('NewSheet') new_sheet['A1'] = 'Data' wb.save('modified.xlsx')
Excel files created or modified by openpyxl contain formulas as strings but not calculated values. Use the provided scripts/recalc.py script to recalculate formulas:
bashpython skills/xlsx/scripts/recalc.py <excel_file> [timeout_seconds]
Example:
bashpython skills/xlsx/scripts/recalc.py output.xlsx 30
The script:
Quick checks to ensure formulas work correctly:
pd.notna()/ in formulas (#DIV/0!)The script returns JSON with error details:
json{ "status": "success", // or "errors_found" "total_errors": 0, // Total error count "total_formulas": 42, // Number of formulas in file "error_summary": { // Only present if errors found "#REF!": { "count": 2, "locations": ["Sheet1!B5", "Sheet1!C10"] } } }
data_only=True to read calculated values: load_workbook('file.xlsx', data_only=True)data_only=True and saved, formulas are replaced with values and permanently lostread_only=True for reading or write_only=True for writingpd.read_excel('file.xlsx', dtype={'id': str})pd.read_excel('file.xlsx', usecols=['A', 'C', 'E'])pd.read_excel('file.xlsx', parse_dates=['date_column'])IMPORTANT: When generating Python code for Excel operations:
For Excel files themselves:
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | fail→fail | 47,425 | 32,521 | -31% | 1 | 1 | 0% | 8,330 | 4,409 | -47% | 0 | 0 | — |
case-02 | fail→fail | 47,050 | 7,787 | -83% | 1 | 1 | 0% | 8,284 | 3,460 | -58% | 0 | 0 | — |
case-03 | fail→fail | 47,514 | 13,481 | -72% | 1 | 1 | 0% | 8,301 | 4,229 | -49% | 0 | 0 | — |
case-04 | pass→pass | 21,643 | 50,379 | +133% | 1 | 1 | 0% | 3,514 | 11,354 | +223% | 0 | 0 | — |
case-05 | fail→pass | 12,474 | 7,130 | -43% | 1 | 1 | 0% | 2,358 | 4,152 | +76% | 0 | 0 | — |
case-06 | fail→pass | 15,329 | 5,273 | -66% | 1 | 1 | 0% | 2,160 | 4,130 | +91% | 0 | 0 | — |
case-07 | fail→pass | 11,296 | 6,090 | -46% | 1 | 1 | 0% | 1,626 | 4,122 | +154% | 0 | 0 | — |
case-08 | fail→fail | 8,807 | 6,257 | -29% | 1 | 1 | 0% | 1,231 | 4,199 | +241% | 0 | 0 | — |
case-09 | pass→pass | 10,637 | 4,137 | -61% | 1 | 1 | 0% | 1,867 | 3,869 | +107% | 0 | 0 | — |
case-10 | pass→pass | 15,767 | 16,788 | +6% | 1 | 1 | 0% | 2,503 | 5,712 | +128% | 0 | 0 | — |
case-11 | fail→pass | 10,464 | 5,465 | -48% | 1 | 1 | 0% | 1,646 | 3,803 | +131% | 0 | 0 | — |
case-12 | pass→pass | 8,820 | 4,144 | -53% | 1 | 1 | 0% | 1,437 | 3,567 | +148% | 0 | 0 | — |
case-13 | pass→pass | 8,983 | 2,931 | -67% | 1 | 1 | 0% | 1,540 | 3,639 | +136% | 0 | 0 | — |
case-14 | pass→pass | 9,498 | 6,536 | -31% | 1 | 1 | 0% | 1,579 | 4,000 | +153% | 0 | 0 | — |
case-15 | fail→fail | 17,208 | 3,643 | -79% | 1 | 1 | 0% | 2,569 | 3,795 | +48% | 0 | 0 | — |
case-16 | pass→pass | 10,248 | 8,489 | -17% | 1 | 1 | 0% | 1,473 | 4,293 | +191% | 0 | 0 | — |
case-17 | pass→pass | 9,985 | 2,977 | -70% | 1 | 1 | 0% | 1,518 | 3,533 | +133% | 0 | 0 | — |
case-18 | pass→fail | 18,790 | 6,854 | -64% | 1 | 1 | 0% | 2,598 | 4,122 | +59% | 0 | 0 | — |
case-19 | pass→pass | 11,057 | 7,492 | -32% | 1 | 1 | 0% | 1,768 | 4,265 | +141% | 0 | 0 | — |
case-20 | pass→pass | 12,008 | 6,031 | -50% | 1 | 1 | 0% | 1,623 | 3,720 | +129% | 0 | 0 | — |
case-21 | pass→pass | 6,027 | 8,304 | +38% | 1 | 1 | 0% | 866 | 3,696 | +327% | 0 | 0 | — |
case-22 | pass→pass | 8,059 | 7,200 | -11% | 1 | 1 | 0% | 1,601 | 4,134 | +158% | 0 | 0 | — |
case-23 | pass→pass | 51,943 | 15,644 | -70% | 1 | 1 | 0% | 8,241 | 6,279 | -24% | 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, and 20 counted toward the lift figure. The other 3 produced results that are not comparable between the two arms, so they are excluded from the headline rather than averaged into it. The headline lift of +13 percentage points is the difference between those two pass rates over the 20 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.