mcpField
X
xlsx-processing-manus

xlsx-processing-manus

github.com/lawve-ai文档处理907101 次安装1 周前更新
代码仓库

关于 xlsx-processing-manus

这是一项用于生成打开后即可浏览的 Excel 工作簿的技能。它根据用户需求指导结构、分析、格式和可视化的选择。

主要功能

  1. 01按用户需求选择功能
  2. 02概览工作表与导航
  3. 03图表和条件格式
  4. 04公式与数字格式指引
  5. 05数据背景与洞察版块
  6. 06统一的工作簿主题

适用场景

  1. 01构建带摘要的多工作表工作簿
  2. 02用图表比较类别数值
  3. 03突出显示阈值和异常值
  4. 04用公式创建可调整模型

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/lawve-ai/awesome-legal-skills --skill xlsx-processing-manus

安装后在 Claude Code 中输入/xlsx-processing-manus确认已加载。

详细介绍

Excel 生成技能

目标

让用户能够立即使用 Excel,并在打开时获取洞察。

核心原则

尽可能丰富视觉呈现,同时确保内容清晰,不增加认知负担。每个视觉元素都应有意义且目的明确——为内容服务,而非用于装饰。


第 1 部分:用户需求与功能匹配

创建任何 Excel 之前,请先思考:

  1. 用户需要什么?——不是“一个 Excel 文件”,而是他们要解决什么问题?
  2. 我能提供什么?——哪些功能能帮助他们?
  3. 如何匹配?——针对具体场景选择合适的功能组合。
功能 ↔ 用户价值对应关系
帮助用户「理解数据」
功能用户价值使用时机
条形图/柱形图一眼看出差异比较不同类别的值
折线图一眼看出趋势时间序列数据
饼图一眼看出占比整体中的部分(≤6 个类别)
数据条无需离开单元格即可比较大小需要快速比较的数值列
色阶热力图效果,让模式一目了然矩阵、范围、分布
迷你图在单个单元格中查看趋势包含历史背景的汇总行
帮助用户「找到重点」
功能用户价值使用时机
预先排序最重要的数据排在前面排名、Top N、优先级
条件突出显示自动凸显关键数据异常值、阈值、Top/Bottom N
图标集一眼看出状态KPI 状态、类别状态(谨慎使用)
粗体/颜色强调区分主要与次要内容汇总行、关键指标
关键洞察部分直接呈现结论分析报告
帮助用户「节省时间」
功能用户价值使用时机
概览工作表首页即为摘要,无需查找所有多工作表文件
预先计算的摘要结果现成,无需手动计算需要统计的数据
统一的数字格式无需调整格式所有数值数据
冻结窗格滚动时仍能看到标题超过 10 行的表格
带链接的工作表索引快速导航,无需猜测超过 3 个工作表的文件
帮助用户「直接使用」
功能用户价值使用时机
筛选器用户可以自行探索数据需要探索性分析时
超链接点击即可导航,无需手动切换跨工作表引用、外部来源
适合打印的布局可直接打印或导出为 PDF用于分享的报告
公式(而非硬编码)更改参数后,结果自动更新模型、预测、可调整的场景
数据验证下拉菜单防止输入错误需要用户输入的模板
帮助用户「信任数据」
功能用户价值使用时机
数据来源说明了解数据来源所有外部数据
生成日期了解数据的新鲜度对时效性有要求的报告
数据时间范围了解涵盖的时期时间序列数据
专业格式看起来可靠所有面向外部的文件
统一精度不必怀疑数据准确性所有数值
帮助用户「获得洞察」
功能用户价值使用时机
对比列(Δ、%)无需手动计算即可比较YoY、MoM、A 与 B
排名列直接显示位次竞争分析、绩效分析
分组汇总按维度汇总结果分段分析
趋势指标(↑↓)一眼看清方向需要关注变化方向时
洞察文本明确说明“这意味着什么”分析报告

第 2 部分:四层实施

第 1 层:结构(如何组织)

目标:逻辑清晰、易于导航,让用户立即找到所需内容。

工作表组织
指南建议
工作表数量3–5 个为宜,最多 7 个
第一个工作表始终命名为「Overview」,包含摘要和导航
工作表顺序从通用到具体(Overview → Data → Analysis)
命名清晰、简洁(例如「Revenue Data」,而非「Sheet1」)
信息架构
  • Overview 工作表必须独立完整:用户无需打开其他工作表,也应能理解核心信息
  • 渐进式披露:先呈现摘要,为希望深入了解的用户提供详细信息
  • 各工作表结构一致:采用相同的布局模式和起始位置
布局规则
元素位置
左边距A 列留空(宽度为 3)
上边距第 1 行留空
内容起始位置单元格 B2
分区间距各分区之间留 1 行空行
表格间距各表格之间留 2 行空行
图表放在所有表格下方(间隔 2 行),或放在相关表格右侧

图表位置:

  • 默认:放在所有表格下方,与内容左对齐
  • 备选:放在单个相关表格的右侧
  • 图表之间以及图表与表格之间不得重叠
独立文本行

对于只有一个文本单元格的行(标题、描述、注释、项目符号),文本会自然延伸到右侧的空单元格中。但如果右侧单元格包含任何内容(包括空格),文本就会被截断。

判断逻辑:

条件操作
确认右侧单元格为空无需操作——文本会自然延伸
右侧单元格可能有内容将单元格合并至内容宽度,或自动换行
文本超出内容区域宽度自动换行 + 手动设置行高

技术说明:仅设置填充和边框不会阻止文本溢出;只有实际单元格内容(包括空格字符)才会阻止溢出。

导航

对于包含 3 个或更多工作表的文件,请在 Overview 中加入工作表索引:

# Sheet Index with hyperlinks
ws['B5'] = "CONTENTS"
ws['B5'].font = Font(name=SERIF_FONT, size=14, bold=True, color=THEME['accent'])

sheets = ["Overview", "Data", "Analysis"]
for i, sheet_name in enumerate(sheets, start=6):
    cell = ws.cell(row=i, column=2, value=sheet_name)
    cell.hyperlink = f"#'{sheet_name}'!A1"
    cell.font = Font(color=THEME['accent'], underline='single')

第 2 层:信息(用户学到什么)

目标:准确、完整、富有洞见——让用户获得知识,而不只是数据。

数字格式

关键规则:

  1. 每个数字单元格都必须设置 number_format——包括输入值和公式结果
  2. 同一列使用相同精度——绝不要在同一列中混用 0.1074 和 1.0
  3. 公式结果没有默认格式——除非明确设置格式,否则会显示原始精度
数据类型格式代码示例
整数#,##01,234,567
小数(1 位)#,##0.01,234.6
小数(2 位)#,##0.001,234.56
百分比0.0%12.3%
货币$#,##0.00$1,234.56

常见错误:只为输入单元格设置格式,却忘记设置公式单元格的格式。

# WRONG: Formula cell without number_format
ws['C10'] = '=C7-C9'  # Will display raw precision like 14.123456789

# CORRECT: Always set number_format for formula cells
ws['C10'] = '=C7-C9'
ws['C10'].number_format = '#,##0.0'  # Displays as 14.1

# Best practice: Define format by column/data type, apply to ALL cells
for row in range(data_start, data_end + 1):
    cell = ws.cell(row=row, column=value_col)
    cell.number_format = '#,##0.0'  # Applies to both values and formulas
数据背景

每组数据都需要背景信息:

元素位置示例
数据来源Overview 或工作表页脚「来源:Company Annual Report 2024」
时间范围标题附近或副标题中「数据来自 2020 年 1 月至 2024 年 12 月」
生成日期Overview 页脚「生成日期:2024-01-15」
定义注释部分或单独的工作表「Revenue = 不含退货的净销售额」
关键洞见

对于分析内容,不要只展示数据——还要告诉用户数据的含义:

ws['B20'] = "KEY INSIGHTS"
ws['B20'].font = Font(name=SERIF_FONT, size=14, bold=True, color=THEME['accent'])

insights = [
    "• Revenue grew 23% YoY, driven primarily by APAC expansion",
    "• Top 3 customers account for 45% of total revenue",
    "• Q4 showed strongest performance across all metrics"
]
for i, insight in enumerate(insights, start=21):
    ws.cell(row=i, column=2, value=insight)
内容完整性
检查项操作
缺失值显示为空白或「N/A」;除非实际值为 0,否则不要显示 0
计算字段添加公式或说明计算方法的注释
缩写首次使用时或在注释中解释
单位在标题中注明(例如「Revenue ($M)」)

第 3 层:视觉(用户看到什么)

目标:外观专业,能立即体现价值,视觉元素服务于内容。

基本设置
from openpyxl.styles import Font, PatternFill, Alignment, Border, Side

# Hide gridlines for cleaner look
ws.sheet_view.showGridLines = False

# Left margin
ws.column_dimensions['A'].width = 3
主题系统

每个工作簿选择一个主题。所有视觉元素都以主题色为基础。

可用主题(根据上下文选择,或由用户指定):

主题主色浅色适用场景
优雅黑2D2D2DE5E5E5奢华、时尚、高端报告(推荐默认主题)
企业蓝1F4E79D6E3F0金融、企业分析
森林绿2E5A4CD4E5DE可持续发展、环境保护
酒红722F37E8D5D7奢侈品牌、葡萄酒行业
板岩灰4A5568E2E8F0科技、现代、简约
海军蓝1E3A5FD3DCE6政府、海事、机构
炭灰36454FDDE1E4专业、管理层
深紫4A235AE1D5E7创意、创新、高端科技
蓝绿色1A5F5FD3E5E5医疗保健、健康
暖棕5D4037E6DDD9自然、有机、手工艺
皇家蓝1A237ED3D5E8学术、机构
橄榄绿556B2FE0E5D5军事、户外

主题配置:

# === THEME CONFIGURATION ===
THEMES = {
    'elegant_black': {
        'primary': '2D2D2D',
        'light': 'E5E5E5',
        'accent': '2D2D2D',
        'chart_colors': ['2D2D2D', '4A4A4A', '6B6B6B', '8C8C8C', 'ADADAD', 'CFCFCF'],
    },
    'corporate_blue': {
        'primary': '1F4E79',
        'light': 'D6E3F0',
        'accent': '1F4E79',
        'chart_colors': ['1F4E79', '2E75B6', '5B9BD5', '9DC3E6', 'BDD7EE', 'DEEBF7'],
    },
    # ... other themes follow same pattern
}

THEME = THEMES['elegant_black']  # Default
SERIF_FONT = 'Source Serif Pro'   # or 'Georgia' as fallback
SANS_FONT = 'Source Sans Pro'     # or 'Calibri' as fallback

主题色的应用方式:

元素颜色背景
文档标题THEME['primary']无
章节标题THEME['primary']无或 THEME['light']
表格标题白色THEME['primary']
数据单元格黑色无或交替使用 F9F9F9
图表元素THEME['chart_colors']—
语义颜色

用于表达数据含义(独立于主题):

语义颜色用途
正向2E7D32增长、盈利、成功
负向C62828下降、亏损、失败
警告F57C00谨慎、注意
行高亮颜色

用于突出显示整行。使用高亮度色调(亮度为 85-95%),以实现轻微区分。

语义Hex色相用途
强调E6F3FF209°最高评分、重要数据
章节FFF3E037°章节分隔符
输入FFFDE755°可编辑单元格
特殊FFF9C455°基准情况、基准值
成功E8F5E9125°已通过、已完成
警告FFCCBC14°需要关注

规则:相同语义使用相同颜色。不同语义使用不同颜色。

HIGHLIGHT = {
    'emphasis': 'E6F3FF',
    'section': 'FFF3E0',
    'input': 'FFFDE7',
    'special': 'FFF9C4',
    'success': 'E8F5E9',
    'warning': 'FFCCBC',
}
字体排版

使用衬线字体 + 无衬线字体搭配。衬线字体用于建立层级(标题、表头);无衬线字体用于数据(表格数字)。

字体搭配(按优先顺序排列):

衬线字体(标题)无衬线字体(数据)备注
Source Serif ProSource Sans ProAdobe 超级字体系列,推荐
IBM Plex SerifIBM Plex Sans现代、企业风格
GeorgiaCalibri预装后备字体

层级:

元素字体大小样式
文档标题衬线字体18-22粗体、主色
章节标题衬线字体12-14粗体、主色
表格标题衬线字体10-11粗体、白色
数据单元格无衬线字体11常规、黑色
注释无衬线字体9-10斜体、666666
# Document title
ws['B2'].font = Font(name=SERIF_FONT, size=18, bold=True, color=THEME['primary'])

# Section header
ws['B6'].font = Font(name=SERIF_FONT, size=14, bold=True, color=THEME['primary'])

# Table header
header_font = Font(name=SERIF_FONT, size=10, bold=True, color='FFFFFF')

# Data cells
data_font = Font(name=SANS_FONT, size=11)

# Notes
notes_font = Font(name=SANS_FONT, size=10, italic=True, color='666666')
数据块定义

数据块是由连续、非空行组成的分组,构成一个需要添加边框的视觉单元。数据块之间以空行分隔。

识别规则:

  1. 从章节标题开始向下扫描
  2. 非空行开始一个数据块
  3. 空行结束当前数据块
  4. 每个数据块都有自己的外框

数据块类型:

类型结构示例
带表头表头行 + 数据行带列标题的表格
不带表头仅数据行后续数据、子表格

示例识别:

Row 5: Section Header "INCOME STATEMENT"   → No border (not a Data Block)
Row 6: Empty                               → Separator
Row 7: Header (Item, Year1, Year2...)      → Data Block 1 starts
Row 8: Revenue, 47061, 48943...            
Row 9: Growth Rate, 4.0%, 3.5%...          → Data Block 1 ends
Row 10: Empty                              → Separator
Row 11: EBITDA, 12121, 12627...            → Data Block 2 starts (no header)
Row 12: EBITDA Margin, 25.8%, 25.8%...     → Data Block 2 ends
Row 13: Empty                              → Separator
Row 14: D&A, 1200, 1224...                 → Data Block 3 starts (no header)
Row 15: EBIT, 10921, 11404...              
Row 16: EBIT Margin, 23.2%, 23.3%...       → Data Block 3 ends

结果:3 个独立的数据块,每个都有自己的外框。

边框规则

推荐样式:仅使用水平边框——更简洁、现代。

每个数据块都必须有:

边框类型位置
外框数据块的 4 条边(上、下、左、右)
表头底边中等粗细,使用主题主色(如果有表头)
内部水平线细线,位于所有行之间
内部垂直线无(省略以保持简洁)

重要:数据块中的每个单元格都必须设置边框。不能只给表头和标签单元格设置边框——数据单元格也需要边框。

# Border definitions
outer_border = Side(style='thin', color='D1D1D1')
header_bottom = Side(style='medium', color=THEME['primary'])
inner_horizontal = Side(style='thin', color='D1D1D1')
no_border = Side(style=None)

def apply_data_block_borders(ws, start_row, end_row, start_col, end_col, has_header=True):
    """
    Apply borders to a Data Block.
    Every cell must be processed—not just headers and labels.
    """
    for row in range(start_row, end_row + 1):
        for col in range(start_col, end_col + 1):
            cell = ws.cell(row=row, column=col)
            
            # Left/Right: outer frame
            left = outer_border if col == start_col else no_border
            right = outer_border if col == end_col else no_border
            
            # Top: outer for first row, inner horizontal for others
            top = outer_border if row == start_row else inner_horizontal
            
            # Bottom: header_bottom for header, outer for last row, inner for middle
            if has_header and row == start_row:
                bottom = header_bottom
            elif row == end_row:
                bottom = outer_border
            else:
                bottom = inner_horizontal
            
            cell.border = Border(left=left, right=right, top=top, bottom=bottom)

非数据块元素(标题、章节标题、独立文本、备注):不加边框。

对齐方式

表头:居中。

数据单元格:

内容水平对齐
短文本(词语)居中
长文本(句子)左对齐 + indent=1
数字右对齐
日期、状态居中

垂直对齐:始终为 center(包括自动换行的文本)。

# Left-aligned text with padding
cell.alignment = Alignment(horizontal='left', vertical='center', indent=1)

# Numbers
cell.alignment = Alignment(horizontal='right', vertical='center')

# Wrapped text
cell.alignment = Alignment(horizontal='left', vertical='center', wrap_text=True, indent=1)
列宽

计算范围:仅限数据块单元格。排除独立文本行、章节标题和备注。

公式:max(max_content_length_in_data_blocks + padding, minimum)

列类型填充最小值备注
标签/文本+415通常为第一列
数字+614为格式化数字(负号、逗号)留出额外空间
长文本+420,最大 40超过最大值时换行

设计约束:不同数据块中的同一列应承担相似的作用。列宽由该列在所有数据块中的最长内容决定。

独立文本行:不要纳入列宽计算。让文本自然延伸,或使用换行/合并单元格。

def calculate_column_width(ws, col, data_block_ranges):
    """
    Calculate column width based only on Data Block content.
    Standalone text rows are excluded.
    
    data_block_ranges: list of (start_row, end_row) tuples
    """
    max_len = 0
    is_numeric = True
    
    for start_row, end_row in data_block_ranges:
        for row in range(start_row, end_row + 1):
            cell = ws.cell(row=row, column=col)
            if cell.value:
                # Get formatted display length
                display_value = str(cell.value)
                max_len = max(max_len, len(display_value))
                if not isinstance(cell.value, (int, float)):
                    is_numeric = False
    
    padding = 6 if is_numeric else 4
    minimum = 14 if is_numeric else 15
    
    return max(max_len + padding, minimum)
行高

必须手动设置——openpyxl 不会自动调整。

行类型高度
文档标题35
章节标题25
表格表头30
标准数据18
自动换行的文本lines × 15 + 10
ws.row_dimensions[2].height = 35   # Title
ws.row_dimensions[5].height = 25   # Section header
ws.row_dimensions[7].height = 30   # Table header
ws.row_dimensions[8].height = 18   # Data row
合并单元格
元素合并?跨度
文档/工作表标题是下方内容的宽度
章节标题是相关表格的宽度
多级表头(父级)是跨越子列
长文本行是内容区域的宽度

何时合并:如果文本超出列边界而被截断,则应合并。如果文本能在单列内完整显示,合并为可选操作。

通常需要合并的情况:

  • 标题和副标题(通常跨越整个内容宽度)
  • 章节标题(跨越相关表格的宽度)
  • KEY INSIGHTS 要点(长句)
  • 备注和免责声明(多句文本)

带背景色的章节标题——合并宽度必须与表格宽度一致:

# Section header spans same width as table below
last_col = 8  # Must match table's last column
ws.merge_cells(f'B6:{get_column_letter(last_col)}6')
ws['B6'] = "KEY METRICS"
ws['B6'].font = Font(name=SERIF_FONT, size=14, bold=True, color=THEME['primary'])
ws['B6'].fill = PatternFill(start_color=THEME['light'], end_color=THEME['light'], fill_type='solid')
ws['B6'].alignment = Alignment(horizontal='left', vertical='center')
数据可视化

数据条:

from openpyxl.formatting.rule import DataBarRule

rule = DataBarRule(start_type='min', end_type='max', color=THEME['primary'])
ws.conditional_formatting.add('C5:C50', rule)

色阶:

from openpyxl.formatting.rule import ColorScaleRule

rule = ColorScaleRule(
    start_type='min', start_color='FFFFFF',
    end_type='max', end_color=THEME['primary']
)
ws.conditional_formatting.add('D5:D50', rule)

图表:

from openpyxl.chart import BarChart, Reference

chart = BarChart()
chart.title = "Revenue by Region"
data = Reference(ws, min_col=3, min_row=4, max_row=10)
cats = Reference(ws, min_col=2, min_row=5, max_row=10)
chart.add_data(data, titles_from_data=True)
chart.set_categories(cats)

# Apply theme colors to chart series
for i, series in enumerate(chart.series):
    series.graphicalProperties.solidFill = THEME['chart_colors'][i % len(THEME['chart_colors'])]

ws.add_chart(chart, "F5")

第 4 层:交互(如何交互)

目标:易于使用且灵活,用户可以探索和处理数据。

冻结窗格

对于行数超过 10 行的表格:

ws.freeze_panes = 'B5'  # Freeze below header row
筛选器

对于行数超过 20 行的表格:

ws.auto_filter.ref = f"B4:{get_column_letter(last_col)}{last_row}"
超链接
# Internal link
cell.hyperlink = "#'Data'!A1"
cell.font = Font(color=THEME['accent'], underline='single')

# External link
cell.hyperlink = "https://example.com"
cell.font = Font(color=THEME['accent'], underline='single')
排序

按最有意义的维度预先排序:

  • 排名 → 按值降序
  • 时间序列 → 按日期升序
  • 按字母排序 → 没有明确优先级时使用
df = df.sort_values('revenue', ascending=False)
可编辑性
  • 如果用户可能会更新输入值,请使用公式
  • 如果数据已定稿,请使用硬编码值
  • 保持公式简单;复杂公式应附上说明

评论

支持 Markdown