[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M7EDJK4NQYY5T175ZJWH7PAB":3,"skill-same:01M7EDJK4NQYY5T175ZJWH7PAB":49},{"skillNo":4,"name":5,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":15,"categories":16,"keywords":17,"publishedAt":18,"linkOnly":19,"markdownContent":20,"markdownBody":20,"frontMatter":21,"refName":22,"commitSha":23,"skillDirectory":24,"forksCount":13,"repositoryHtmlUrl":25,"repositoryHomepageUrl":6,"ownerHtmlUrl":26,"ownerBlogUrl":6,"ownerDescription":27,"updatedAt":28,"install":29,"resources":42},"01M7EDJK4NQYY5T175ZJWH7PAB","xlsx",null,"jonahthan433\u002FCortexOS","jonahthan433","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F211465495?v=4","01M7ECH9HPHGA89DCXHHJBTS3C","jonah.ai","01M7ECH9JCEM45DZMWPT7148S1",0,"Apache-2.0","https:\u002F\u002Fgithub.com\u002Fjonahthan433\u002FCortexOS\u002Fblob\u002Fmain\u002Fskills\u002Fimported\u002Fproductivity\u002Fxlsx\u002FSKILL.md",[],[],"2026-11-15 14:19:17",false,"# xlsx\n\n# Xlsx Skill\n\nWork with Excel .xlsx workbooks using Python and openpyxl: build styled\nmulti-sheet workbooks with formulas and charts, inspect or dump existing\nfiles, edit cells and structure, and convert to\u002Ffrom CSV. All helper\nscripts are argparse CLIs that print JSON and use explicit UTF-8 I\u002FO.\n\n## When to Use\n\n- Creating .xlsx reports: multiple sheets, number formats, styling,\n  merged cells, freeze panes, autofilter, conditional formatting,\n  charts, data-validation dropdowns, native Excel tables, defined\n  names, hyperlinks, cell notes, sheet protection.\n- Reading a workbook: sheet inventory, dumping data as JSON or CSV,\n  listing formulas vs cached values, notes, defined names, tables.\n- Editing existing files: set cells, append rows, insert\u002Fdelete\n  rows\u002Fcolumns (reference-aware via `xlsx_restructure.py`),\n  copy\u002Frename sheets, tables, names, notes, protection.\n- Recalculating formulas headlessly via LibreOffice\n  (`xlsx_recalc.py`).\n- CSV interop with type inference and non-UTF-8 encodings.\n- Not for the legacy .xls binary format (use LibreOffice to convert\n  first: `soffice --headless --convert-to xlsx old.xls`).\n\n## Prerequisites\n\n- Python 3.10+ with `openpyxl` (`pip install openpyxl`). No other\n  third-party packages are needed; everything else is stdlib.\n- Optional: LibreOffice (`soffice`) for headless recalculation or\n  format conversion.\n\n## How to Run\n\nRun the helper scripts with the `terminal` tool from this skill's\n`scripts\u002F` directory (every script supports `--help`):\n\n```bash\npython scripts\u002Fxlsx_create.py spec.json report.xlsx   # build from JSON spec\npython scripts\u002Fxlsx_read.py report.xlsx --sheets      # inventory\npython scripts\u002Fxlsx_read.py report.xlsx --json --sheet Data\npython scripts\u002Fxlsx_read.py report.xlsx --formulas\npython scripts\u002Fxlsx_edit.py report.xlsx --sheet Data --set B2=42 --recalc\npython scripts\u002Fxlsx_restructure.py report.xlsx --sheet Data --insert-rows 3:2\npython scripts\u002Fxlsx_recalc.py report.xlsx\npython scripts\u002Fcsv_to_xlsx.py data.csv out.xlsx --encoding utf-8\npython scripts\u002Fxlsx_to_csv.py report.xlsx out.csv --sheet Data\n```\n\nAuthor the JSON spec with `write_file`, inspect script JSON output with\n`read_file` or directly from stdout.\n\n## Quick Reference\n\n| Task | Command |\n|---|---|\n| Create workbook from spec | `xlsx_create.py spec.json out.xlsx` |\n| Sheet names + dimensions | `xlsx_read.py f.xlsx --sheets` |\n| Dump sheet as JSON | `xlsx_read.py f.xlsx --json --sheet S` |\n| Dump sheet as CSV | `xlsx_read.py f.xlsx --csv --out d.csv` |\n| List formulas + cached values | `xlsx_read.py f.xlsx --formulas` |\n| Set a cell \u002F formula | `xlsx_edit.py f.xlsx --set \"A1==SUM(B:B)\"` |\n| Append a row | `xlsx_edit.py f.xlsx --append '[1,\"x\",true]'` |\n| Insert 2 rows, refs NOT shifted | `xlsx_edit.py f.xlsx --insert-rows 3:2` |\n| Insert 2 rows, refs shifted | `xlsx_restructure.py f.xlsx --insert-rows 3:2` |\n| Delete a column, refs shifted | `xlsx_restructure.py f.xlsx --delete-cols B` |\n| Create a native table | `xlsx_edit.py f.xlsx --add-table Sales:A1:C9` |\n| Append inside a table | `--table-append 'Sales=[\"West\",5]'` |\n| List tables | `xlsx_edit.py f.xlsx --list-tables` |\n| Defined names | `--define-name \"Rates='Data'!$B$2:$B$9\"` \u002F `--delete-name Rates` \u002F `xlsx_read.py f.xlsx --names` |\n| Hyperlink | `--hyperlink \"A1=https:\u002F\u002Fexample.com|Docs\"` |\n| Cell note | `--note \"B2=Check this|Reviewer\"`; read via `xlsx_read.py f.xlsx --notes` |\n| Protect sheet (see Pitfalls) | `--protect your-password --unlock B2:B9` |\n| Recalculate via LibreOffice | `xlsx_recalc.py f.xlsx` |\n| Copy \u002F rename sheet | `--copy-sheet Src:New --rename-sheet Old:New` |\n| Force recalc on open | `xlsx_edit.py f.xlsx --recalc` |\n| CSV -> styled xlsx | `csv_to_xlsx.py in.csv out.xlsx` |\n| xlsx -> CSV | `xlsx_to_csv.py f.xlsx out.csv --encoding utf-8` |\n\n## Procedure\n\n1. **Create**: write a JSON spec (schema documented in\n   `xlsx_create.py --help` and its docstring). Each sheet supports\n   `rows` (scalars or styled cell objects), sparse `cells` overrides,\n   `column_widths`, `row_heights`, `merges`, `freeze_panes`,\n   `autofilter`, `conditional_formats` (cell_is rules and color\n   scales), `charts` (bar\u002Fline\u002Fpie from cell ranges),\n   `validations` (list dropdowns), `tables` (native Excel tables with\n   a style name), and `protection`. Workbook-level `defined_names`\n   maps names to refs. Cell objects also take `hyperlink` and `note`.\n   Typed values: JSON numbers\u002Fbools\n   pass through; dates use `{\"value\": \"2026-01-31\", \"type\": \"date\"}`.\n   Number formats are Excel format strings: currency `\"$#,##0.00\"`,\n   percent `\"0.0%\"`, date `\"yyyy-mm-dd\"`.\n2. **Formulas**: set with `\"formula\": \"SUM(B2:B9)\"` in the spec or\n   `--set \"C1==SUM(A:A)\"` in the editor. When writing formulas, add\n   `\"full_calc_on_load\": true` (spec) or `--recalc` (editor); this sets\n   the workbook's `fullCalcOnLoad` flag so Excel\u002FLibreOffice recompute\n   everything on open. openpyxl itself NEVER evaluates formulas.\n3. **Read**: `--sheets` for inventory (names, dimensions, merged\n   ranges, chart count, tables, protection, defined names),\n   `--json`\u002F`--csv` for data, `--formulas` to\n   pair each formula string with its cached result, `--notes` for\n   cell comments, `--names` for defined names. Cached results\n   exist only if the file was last saved by a real spreadsheet app;\n   files fresh from openpyxl return `null` there. To materialize\n   results headlessly run `xlsx_recalc.py file.xlsx` (uses\n   LibreOffice; prints `{\"recalculated\": false, ...}` and exits 0\n   when `soffice` is absent), then reload with `--data-only`.\n4. **Edit**: `xlsx_edit.py` applies renames\u002Fcopies first, then\n   structural row\u002Fcolumn changes, then `--set`\u002F`--append`. It edits in\n   place unless `--out` is given — copy the file first if you need the\n   original.\n5. **Restructure**: for insert\u002Fdelete on sheets that have formulas,\n   merges, tables, or filters, use `xlsx_restructure.py` instead of\n   `xlsx_edit.py`. It rewrites formula references on ALL sheets\n   (absolute `$` refs, ranges, cross-sheet refs), shifts merges,\n   autofilter, freeze panes, validation and conditional-format\n   ranges, table refs, defined names, and row\u002Fcolumn dimensions, then\n   prints a JSON report including a `not_shifted` list. Rules and\n   limits: `references\u002Frestructuring.md`.\n6. **CSV interop**: `csv_to_xlsx.py` infers int\u002Ffloat\u002Fbool\u002FISO-date\n   per cell and styles the header row; `xlsx_to_csv.py` writes ISO\n   dates and blank strings for empty cells. Both default to UTF-8 and\n   accept `--encoding` (e.g. `utf-8-sig` for Excel-friendly BOM,\n   `cp1252` for legacy Windows exports).\n\n## Converting to PDF\n\nLibreOffice converts headlessly (also works for CSV export of a single\nsheet):\n\n```bash\nsoffice --headless --convert-to pdf report.xlsx --outdir out\u002F\nsoffice --headless --convert-to csv report.xlsx --outdir out\u002F  # 1st sheet only\n```\n\nOnly the first sheet lands in a CSV; for other sheets use\n`xlsx_to_csv.py --sheet NAME`. If `soffice` is missing, install\nLibreOffice or hand the file to the user unconverted.\n\n## Pitfalls\n\n- **openpyxl does not calculate.** Formula results are available only\n  via `load_workbook(path, data_only=True)` and only when the file was\n  previously saved by Excel\u002FLibreOffice. Otherwise you get `None`.\n- **`xlsx_edit.py` insert\u002Fdelete does not shift references** (raw\n  openpyxl behavior). Use `xlsx_restructure.py`, which does — but even\n  it cannot move chart anchors, images, or conditional-format RULE\n  formulas; read its JSON report's `not_shifted` list and\n  `references\u002Frestructuring.md`.\n- **Sheet protection is NOT security.** `--protect` sets the standard\n  xlsx sheet-protection hash: it signals \"don't edit this\" to\n  well-behaved apps and nothing more. Anyone can strip it by editing\n  the zip's XML or unchecking it in LibreOffice. Never rely on it for\n  confidentiality or integrity; it does not encrypt anything.\n- **`data_only=True` then save** silently discards all formulas\n  (cached values replace them). Never save a workbook loaded that way\n  unless that is the goal.\n- **Loading strips charts\u002Fimages**: openpyxl does not round-trip\n  charts, so editing a charted workbook and saving drops the charts.\n  Re-add charts after editing, or avoid re-saving charted files.\n- **CSV locale traps**: always pass explicit encodings (the scripts\n  already do) and remember European CSVs often use `;` delimiters and\n  decimal commas — use `--delimiter ';'` and expect strings like\n  `\"12,5\"` to stay strings.\n- **Dates are datetimes**: Excel stores dates as serial numbers;\n  openpyxl returns `datetime`\u002F`date` objects. Dumps here emit ISO\n  strings.\n- Sheet names are capped at 31 chars and reject `[ ] : * ? \u002F \\`.\n\n## Verification\n\n- After creating: `xlsx_read.py out.xlsx --sheets` and confirm sheet\n  names, dimensions, merged ranges, and chart counts match intent.\n- Dump data with `--json` and compare against the source values.\n- After edits: re-dump the touched range; if formulas were written,\n  confirm `--formulas` lists them and that `--recalc` was applied.\n- After `xlsx_restructure.py`: read its JSON report, then re-run\n  `--formulas` and `--sheets` to confirm references and ranges landed\n  where expected.\n- For a full visual check, open in LibreOffice:\n  `soffice --headless --convert-to pdf out.xlsx` and inspect the PDF.\n",{},"main","38b32c99e7ed0b8e215d638e92cfa452c1ec3079","skills\u002Fimported\u002Fproductivity\u002Fxlsx","https:\u002F\u002Fgithub.com\u002Fjonahthan433\u002FCortexOS","https:\u002F\u002Fgithub.com\u002Fjonahthan433","AI Consultant","2026-10-24 05:13:39",{"source":7,"skillName":5,"commands":30,"prompt":40,"zipAvailable":41},[31,34,37],{"tool":32,"command":33},"npx","npx skills add jonahthan433\u002FCortexOS --skill xlsx",{"tool":35,"command":36},"bunx","bunx skills add jonahthan433\u002FCortexOS --skill xlsx",{"tool":38,"command":39},"pnpm","pnpm dlx skills add jonahthan433\u002FCortexOS --skill xlsx","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fjonahthan433\u002FCortexOS\u002Fblob\u002Fmain\u002Fskills\u002Fimported\u002Fproductivity\u002Fxlsx\u002FSKILL.md",true,[43],{"path":44,"resourceType":45,"resourceTypeDesc":46,"sizeBytes":47,"sourceHtmlUrl":48},"skill.json","REFERENCE","参考文档",310,"https:\u002F\u002Fgithub.com\u002Fjonahthan433\u002FCortexOS\u002Fblob\u002Fmain\u002Fskills\u002Fimported\u002Fproductivity\u002Fxlsx\u002Fskill.json",[50,56,62,68,74,80],{"skillNo":51,"name":52,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":53,"categories":54,"keywords":55,"publishedAt":18},"01M7EDQZDQX3Q8Y7GCQX6KN9V7","opportunity-brief","https:\u002F\u002Fgithub.com\u002Fjonahthan433\u002FCortexOS\u002Fblob\u002Fmain\u002Fskills\u002Fsales\u002Fopportunity-brief\u002FSKILL.md",[],[],{"skillNo":57,"name":58,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":59,"categories":60,"keywords":61,"publishedAt":18},"01M7EDQYA0V9Y99VKBREJJ3MRT","morning-intel","https:\u002F\u002Fgithub.com\u002Fjonahthan433\u002FCortexOS\u002Fblob\u002Fmain\u002Fskills\u002Fresearch\u002Fmorning-intel\u002FSKILL.md",[],[],{"skillNo":63,"name":64,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":65,"categories":66,"keywords":67,"publishedAt":18},"01M7EDQVX1JVY0B6PDHKKGM19G","decision-brief","https:\u002F\u002Fgithub.com\u002Fjonahthan433\u002FCortexOS\u002Fblob\u002Fmain\u002Fskills\u002Fresearch\u002Fdecision-brief\u002FSKILL.md",[],[],{"skillNo":69,"name":70,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":71,"categories":72,"keywords":73,"publishedAt":18},"01M7EDQV1GENZAC2SZSD8KZ3GM","weekly-review","https:\u002F\u002Fgithub.com\u002Fjonahthan433\u002FCortexOS\u002Fblob\u002Fmain\u002Fskills\u002Fproductivity\u002Fweekly-review\u002FSKILL.md",[],[],{"skillNo":75,"name":76,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":77,"categories":78,"keywords":79,"publishedAt":18},"01M7EDQT2KETJ1Y3CGVN9EKW2J","system-health","https:\u002F\u002Fgithub.com\u002Fjonahthan433\u002FCortexOS\u002Fblob\u002Fmain\u002Fskills\u002Fops\u002Fsystem-health\u002FSKILL.md",[],[],{"skillNo":81,"name":82,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":83,"categories":84,"keywords":85,"publishedAt":18},"01M7EDQQN2JK3XPWMS1M4T0F3K","backup-restore","https:\u002F\u002Fgithub.com\u002Fjonahthan433\u002FCortexOS\u002Fblob\u002Fmain\u002Fskills\u002Fops\u002Fbackup-restore\u002FSKILL.md",[],[]]