← 返回 Skills 市场
365
总下载
0
收藏
1
当前安装
2
版本数
在 OpenClaw 中安装
/install chart-maker
功能描述
Data visualization chart generator. Use when user needs to create charts from data for reports, presentations, or documents. Supports bar, line, pie, scatter...
使用说明 (SKILL.md)
Chart Generator
Professional data visualization chart generator for reports, presentations, and documents.
Features
- 📊 Multiple Chart Types: Bar, line, pie, scatter, radar, area, stacked
- 📁 Multiple Data Sources: CSV, Excel, JSON, manual, web, document extraction
- 🎨 Professional Styling: Clean, publication-ready charts with custom options
- 📐 Flexible Output: PNG, SVG, PDF, Word, Excel, Markdown, HTML
- 🔗 Embed Support: Direct embedding into documents
- 🌍 Multi-Language: Chinese, English, Japanese, Korean (no encoding issues)
- ✅ Cross-Platform: Windows, macOS, Linux
Supported Chart Types
| Type | Use Case | Best For |
|---|---|---|
| Bar Chart | Compare values | Sales, rankings |
| Line Chart | Show trends | Time series, growth |
| Pie Chart | Show proportions | Market share, composition |
| Scatter Plot | Show correlation | Data relationships |
| Radar Chart | Multi-dimension | Performance comparison |
| Area Chart | Cumulative values | Stacked data |
| Stacked Bar | Composition | Multi-category breakdown |
Trigger Conditions
- "帮我画图" / "Create a chart"
- "生成柱状图" / "Generate bar chart"
- "数据可视化" / "Data visualization"
- "做一个趋势图" / "Make a trend chart"
- "图表分析" / "Chart analysis"
- "chart-generator"
Step 1: Understand Requirements
请提供以下信息:
图表类型:(柱状图/折线图/饼图/散点图/雷达图)
数据来源:(手动输入/CSV/Excel/JSON)
数据内容:
标题:
X轴标签:
Y轴标签:
输出格式:(PNG/SVG)
颜色要求:(默认/自定义)
Step 2: Generate Chart
Python Script Template
python3 \x3C\x3C 'PYEOF'
import os
import matplotlib.pyplot as plt
import matplotlib
import pandas as pd
import numpy as np
from matplotlib import font_manager
# 设置中文字体
plt.rcParams['font.sans-serif'] = ['Noto Sans SC', 'SimHei', 'DejaVu Sans']
plt.rcParams['axes.unicode_minus'] = False
class ChartGenerator:
def __init__(self):
self.fig = None
self.ax = None
def create_bar_chart(self, labels, values, title='',
xlabel='', ylabel='',
color='#3182ce', output_path=None):
"""Create bar chart"""
self.fig, self.ax = plt.subplots(figsize=(10, 6))
bars = self.ax.bar(labels, values, color=color, edgecolor='white', linewidth=0.5)
# Add value labels on bars
for bar in bars:
height = bar.get_height()
self.ax.text(bar.get_x() + bar.get_width()/2., height,
f'{height:,.0f}',
ha='center', va='bottom', fontsize=10)
self.ax.set_title(title, fontsize=16, fontweight='bold', pad=20)
self.ax.set_xlabel(xlabel, fontsize=12)
self.ax.set_ylabel(ylabel, fontsize=12)
# Clean styling
self.ax.spines['top'].set_visible(False)
self.ax.spines['right'].set_visible(False)
self.ax.grid(axis='y', alpha=0.3)
plt.tight_layout()
if output_path:
self.fig.savefig(output_path, dpi=150, bbox_inches='tight')
plt.close()
return output_path
return self.fig
def create_line_chart(self, x_data, y_data_list, labels=None,
title='', xlabel='', ylabel='',
colors=None, output_path=None):
"""Create line chart"""
self.fig, self.ax = plt.subplots(figsize=(10, 6))
if colors is None:
colors = ['#3182ce', '#48bb78', '#ed8936', '#e53e3e', '#9f7aea']
for i, y_data in enumerate(y_data_list):
color = colors[i % len(colors)]
label = labels[i] if labels and i \x3C len(labels) else f'Series {i+1}'
self.ax.plot(x_data, y_data, marker='o', linewidth=2,
color=color, label=label, markersize=6)
self.ax.set_title(title, fontsize=16, fontweight='bold', pad=20)
self.ax.set_xlabel(xlabel, fontsize=12)
self.ax.set_ylabel(ylabel, fontsize=12)
if labels:
self.ax.legend(loc='best', framealpha=0.9)
self.ax.spines['top'].set_visible(False)
self.ax.spines['right'].set_visible(False)
self.ax.grid(alpha=0.3)
plt.tight_layout()
if output_path:
self.fig.savefig(output_path, dpi=150, bbox_inches='tight')
plt.close()
return output_path
return self.fig
def create_pie_chart(self, labels, values, title='',
colors=None, output_path=None):
"""Create pie chart"""
self.fig, self.ax = plt.subplots(figsize=(8, 8))
if colors is None:
colors = ['#3182ce', '#48bb78', '#ed8936', '#e53e3e', '#9f7aea',
'#38b2ac', '#d69e2e', '#667eea']
wedges, texts, autotexts = self.ax.pie(
values, labels=labels, colors=colors[:len(values)],
autopct='%1.1f%%', startangle=90,
textprops={'fontsize': 11}
)
for autotext in autotexts:
autotext.set_color('white')
autotext.set_fontweight('bold')
self.ax.set_title(title, fontsize=16, fontweight='bold', pad=20)
plt.tight_layout()
if output_path:
self.fig.savefig(output_path, dpi=150, bbox_inches='tight')
plt.close()
return output_path
return self.fig
def create_scatter_plot(self, x_data, y_data, title='',
xlabel='', ylabel='',
color='#3182ce', output_path=None):
"""Create scatter plot"""
self.fig, self.ax = plt.subplots(figsize=(10, 6))
self.ax.scatter(x_data, y_data, c=color, alpha=0.6, s=50)
# Add trend line
z = np.polyfit(x_data, y_data, 1)
p = np.poly1d(z)
self.ax.plot(x_data, p(x_data), '--', color='#e53e3e', alpha=0.8, label='Trend')
self.ax.set_title(title, fontsize=16, fontweight='bold', pad=20)
self.ax.set_xlabel(xlabel, fontsize=12)
self.ax.set_ylabel(ylabel, fontsize=12)
self.ax.legend()
self.ax.spines['top'].set_visible(False)
self.ax.spines['right'].set_visible(False)
self.ax.grid(alpha=0.3)
plt.tight_layout()
if output_path:
self.fig.savefig(output_path, dpi=150, bbox_inches='tight')
plt.close()
return output_path
return self.fig
def create_multi_bar_chart(self, labels, data_dict, title='',
xlabel='', ylabel='', output_path=None):
"""Create grouped bar chart"""
self.fig, self.ax = plt.subplots(figsize=(12, 6))
x = np.arange(len(labels))
width = 0.8 / len(data_dict)
colors = ['#3182ce', '#48bb78', '#ed8936', '#e53e3e', '#9f7aea']
for i, (name, values) in enumerate(data_dict.items()):
offset = (i - len(data_dict)/2 + 0.5) * width
bars = self.ax.bar(x + offset, values, width, label=name,
color=colors[i % len(colors)], edgecolor='white')
self.ax.set_title(title, fontsize=16, fontweight='bold', pad=20)
self.ax.set_xlabel(xlabel, fontsize=12)
self.ax.set_ylabel(ylabel, fontsize=12)
self.ax.set_xticks(x)
self.ax.set_xticklabels(labels)
self.ax.legend()
self.ax.spines['top'].set_visible(False)
self.ax.spines['right'].set_visible(False)
self.ax.grid(axis='y', alpha=0.3)
plt.tight_layout()
if output_path:
self.fig.savefig(output_path, dpi=150, bbox_inches='tight')
plt.close()
return output_path
return self.fig
def load_from_csv(self, csv_path, x_col=None, y_cols=None):
"""Load data from CSV file"""
df = pd.read_csv(csv_path)
if x_col is None:
x_col = df.columns[0]
if y_cols is None:
y_cols = [col for col in df.columns if col != x_col]
return {
'x': df[x_col].tolist(),
'y': {col: df[col].tolist() for col in y_cols},
'df': df
}
def load_from_excel(self, excel_path, sheet_name=0, x_col=None, y_cols=None):
"""Load data from Excel file"""
df = pd.read_excel(excel_path, sheet_name=sheet_name)
if x_col is None:
x_col = df.columns[0]
if y_cols is None:
y_cols = [col for col in df.columns if col != x_col]
return {
'x': df[x_col].tolist(),
'y': {col: df[col].tolist() for col in y_cols},
'df': df
}
def load_from_json(self, json_path):
"""Load data from JSON file"""
import json
with open(json_path, 'r', encoding='utf-8') as f:
data = json.load(f)
return data
def load_from_directory(self, dir_path, file_pattern='*.csv'):
"""Load and aggregate data from multiple files in directory"""
import glob
all_data = []
for file_path in glob.glob(os.path.join(dir_path, file_pattern)):
if file_path.endswith('.csv'):
df = pd.read_csv(file_path)
elif file_path.endswith('.xlsx'):
df = pd.read_excel(file_path)
else:
continue
df['source_file'] = os.path.basename(file_path)
all_data.append(df)
if all_data:
return pd.concat(all_data, ignore_index=True)
return pd.DataFrame()
def extract_data_from_text(self, text):
"""Extract numerical data from text content"""
import re
# Find patterns like "Sales: 100" or "销售额:100万"
patterns = [
r'(\w+)\s*[::]\s*(\d+(?:\.\d+)?)',
r'(\d+(?:\.\d+)?)\s*[::]\s*(\w+)',
]
data = {}
for pattern in patterns:
matches = re.findall(pattern, text)
for match in matches:
if len(match) == 2:
key, value = match
try:
data[key] = float(value)
except ValueError:
pass
return data
def save_to_png(self, output_path, dpi=150):
"""Save chart as PNG"""
if self.fig:
self.fig.savefig(output_path, dpi=dpi, bbox_inches='tight',
facecolor='white', edgecolor='none')
return output_path
def save_to_svg(self, output_path):
"""Save chart as SVG"""
if self.fig:
self.fig.savefig(output_path, format='svg', bbox_inches='tight',
facecolor='white', edgecolor='none')
return output_path
def save_to_pdf(self, output_path):
"""Save chart as PDF"""
if self.fig:
self.fig.savefig(output_path, format='pdf', bbox_inches='tight',
facecolor='white', edgecolor='none')
return output_path
def save_to_base64(self, format='png'):
"""Convert chart to base64 string for embedding"""
import io
import base64
if self.fig:
buffer = io.BytesIO()
self.fig.savefig(buffer, format=format, bbox_inches='tight',
facecolor='white', edgecolor='none')
buffer.seek(0)
img_str = base64.b64encode(buffer.read()).decode()
return f'data:image/{format};base64,{img_str}'
def embed_in_markdown(self, title='', caption=''):
"""Generate markdown with embedded chart"""
base64_img = self.save_to_base64('png')
md = f'\
'
if title:
md += f'## {title}\
\
'
md += f'\
'
if caption:
md += f'\
*{caption}*\
'
return md
def embed_in_html(self, title='', width='100%'):
"""Generate HTML with embedded chart"""
base64_img = self.save_to_base64('png')
html = f'''
\x3Cdiv class="chart-container">
{f'\x3Ch3>{title}\x3C/h3>' if title else ''}
\x3Cimg src="{base64_img}" alt="{title}" style="max-width: {width};">
\x3C/div>
'''
return html
def save_to_word(self, output_path, title='', caption=''):
"""Save chart to Word document"""
from docx import Document
from docx.shared import Inches
doc = Document()
if title:
doc.add_heading(title, level=2)
# Save chart as temporary image
temp_img = output_path.replace('.docx', '_temp.png')
self.save_to_png(temp_img)
# Add image to document
doc.add_picture(temp_img, width=Inches(6))
if caption:
last_para = doc.paragraphs[-1]
last_para.alignment = 1 # Center
doc.save(output_path)
# Clean up temp file
if os.path.exists(temp_img):
os.remove(temp_img)
return output_path
# Example usage
generator = ChartGenerator()
output_dir = os.environ.get('OPENCLAW_WORKSPACE', os.getcwd())
# Bar chart
labels = ['Q1', 'Q2', 'Q3', 'Q4']
values = [150000, 180000, 220000, 280000]
generator.create_bar_chart(
labels, values,
title='2026 Quarterly Sales',
xlabel='Quarter',
ylabel='Sales ($)',
output_path=os.path.join(output_dir, 'bar_chart.png')
)
# Line chart
months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun']
product_a = [100, 120, 140, 160, 180, 200]
product_b = [80, 95, 110, 130, 150, 170]
generator.create_line_chart(
months, [product_a, product_b],
labels=['Product A', 'Product B'],
title='Sales Trend',
xlabel='Month',
ylabel='Sales',
output_path=os.path.join(output_dir, 'line_chart.png')
)
# Pie chart
pie_labels = ['Product A', 'Product B', 'Product C', 'Others']
pie_values = [35, 25, 20, 20]
generator.create_pie_chart(
pie_labels, pie_values,
title='Market Share',
output_path=os.path.join(output_dir, 'pie_chart.png')
)
print(f"✅ Charts generated in: {output_dir}")
PYEOF
Data Sources (数据来源)
From CSV
generator = ChartGenerator()
data = generator.load_from_csv('data.csv', x_col='Month', y_cols=['Sales', 'Profit'])
generator.create_line_chart(
data['x'],
[data['y']['Sales'], data['y']['Profit']],
labels=['Sales', 'Profit'],
title='Monthly Performance'
)
From Excel
data = generator.load_from_excel('report.xlsx', sheet_name='Sheet1')
Manual Input
labels = ['A', 'B', 'C', 'D']
values = [100, 200, 150, 300]
generator.create_bar_chart(labels, values)
Styling Options (样式选项)
Colors
# Single color
color='#3182ce' # Blue
# Multiple colors
colors=['#3182ce', '#48bb78', '#ed8936', '#e53e3e']
Size
# Default size
figsize=(10, 6)
# Large for presentations
figsize=(16, 9)
# Square for reports
figsize=(8, 8)
Security Notes
- ✅ No network calls or external endpoints
- ✅ No credentials or API keys required
- ✅ Local file processing only
- ✅ Open source dependencies (matplotlib, pandas)
- ✅ No data uploaded to external servers
Notes
- Uses matplotlib for chart generation
- Supports CSV, Excel, and manual data input
- Output formats: PNG, SVG, PDF
- Chinese font support with Noto Sans SC
- Cross-platform compatible
安全使用建议
This skill appears to do what it says: generate charts by running Python code locally. Before installing/using it:
- Ensure python3 and the required Python packages (matplotlib, pandas, openpyxl, python-docx, pillow) are installed from trusted package indexes (pip). The skill will not auto-install them.
- Understand that the skill runs Python code on the host (via a heredoc); do not feed it sensitive secrets or allow it to process untrusted data you wouldn't want executed. If you paste data or URLs, verify what gets inserted into the script to avoid injection.
- The SKILL.md mentions 'web' and 'document extraction' as data sources — the instructions do not automatically fetch remote content; supplying URLs or files is under your control.
- If you need offline or air-gapped guarantees, run the provided scripts locally in a controlled environment (virtualenv/container).
Overall: coherent for chart generation, but because it executes Python code locally, treat it like any tool that runs code and verify inputs and dependencies before use.
功能分析
Type: OpenClaw Skill
Name: chart-maker
Version: 1.0.2
The skill bundle is a legitimate data visualization tool that uses standard Python libraries (matplotlib, pandas) to generate various chart types. The code in SKILL.md is well-structured, lacks any network communication, and focuses entirely on processing local data files (CSV, Excel, JSON) and rendering images. No indicators of data exfiltration, malicious execution, or prompt injection were found.
能力评估
Purpose & Capability
Name/description (chart generation) align with the requested binary (python3) and the Python/matplotlib/pandas toolchain referenced in SKILL.md. Declared features (Excel/Word output) match the listed Python libraries (openpyxl, python-docx).
Instruction Scope
SKILL.md contains concrete Python script templates that will be run locally (via a heredoc calling python3). The templates read/process data and save chart files — which is appropriate for the stated purpose. Caution: the skill instructs running generated Python code with user-supplied data; if user inputs are interpolated into the script without sanitization this could allow code-injection or execution of unintended commands. SKILL.md does not instruct any network calls or access to unrelated system paths.
Install Mechanism
This is instruction-only (no install spec, no code files) which minimizes risk. Minor inconsistency: SKILL.md frontmatter lists a 'dependencies' line ('pip install matplotlib pandas openpyxl python-docx pillow') but the registry metadata contains no install step — packages will not be automatically installed by the skill. Users must install these packages themselves for the skill to work.
Credentials
The skill requests no environment variables, credentials, or config paths. The requested tools/libs are proportional to chart generation and document export.
Persistence & Privilege
always is false and default autonomy is allowed (normal for skills). The skill does not request permanent presence or system-wide config changes.
如何使用
- 确保已安装 OpenClaw(本地或 Docker 部署)
- 在对话框中输入安装命令:
/install chart-maker - 安装完成后,直接呼叫该 Skill 的名称或使用
/chart-maker触发 - 根据 Skill 的参数说明提供必要输入,即可获得结构化输出
版本历史
v1.0.2
修复依赖声明:添加python-docx和pillow依赖
v1.0.1
专业数据可视化图表生成器:支持多种图表类型、数据来源、输出格式,可嵌入Word/PDF/HTML
元数据
常见问题
Chart Generator 是什么?
Data visualization chart generator. Use when user needs to create charts from data for reports, presentations, or documents. Supports bar, line, pie, scatter... 它是一个面向 Claude Code / OpenClaw 的 AI Agent Skill 插件,目前累计下载 365 次。
如何安装 Chart Generator?
在 OpenClaw 或 Claude Code 对话框中运行命令「/install chart-maker」即可一键安装,无需额外配置。
Chart Generator 是免费的吗?
是的,Chart Generator 完全免费,采用 MIT-0 许可证,可自由下载、安装和使用。
Chart Generator 支持哪些平台?
Chart Generator 跨平台运行,可在任意部署了 OpenClaw / Claude Code 的环境中使用(cross-platform)。
谁开发了 Chart Generator?
由 ToBeWin(@tobewin)开发并维护,当前版本 v1.0.2。
推荐 Skills