npx skills add ...
npx skills add jmsktm/claude-settings --skill spreadsheet-builder
Create Excel and CSV files with formulas, formatting, charts, and data analysis
npx skills add jmsktm/claude-settings --skill spreadsheet-builder
The Spreadsheet Builder skill enables creation of professional Excel (.xlsx) and CSV files with advanced formatting, formulas, charts, and data analysis features. Using libraries like exceljs and xlsx, this skill handles everything from simple data exports to complex financial models and dashboards.
Generate data reports, financial statements, inventory lists, analysis dashboards, and any tabular data visualization. Support for multiple sheets, cell styling, conditional formatting, formulas, pivot tables, and charts makes this a comprehensive solution for spreadsheet automation.
Purpose: Build a simple Excel file with formatted data
Steps:
exceljs and create Workbook instanceImplementation:
Purpose: Create spreadsheets with automatic calculations and formulas
Steps:
Implementation:
Purpose: Highlight cells based on rules and thresholds
Steps:
Implementation:
Purpose: Add charts to visualize data trends and comparisons
Steps:
Implementation:
Purpose: Create complex workbooks with multiple related sheets
Steps:
Implementation:
Purpose: Create simple CSV files for data exchange
Steps:
Implementation:
| Action | Command/Trigger |
|---|---|
| Create Excel workbook | "create excel file with [data]" |
| Generate CSV | "export [data] to csv" |
| Add formulas | "add formulas to spreadsheet" |
| Apply formatting | "format excel cells [style]" |
| Create chart | "add chart to workbook" |
| Multi-sheet workbook | "create workbook with [sheets]" |
| Conditional formatting | "apply conditional formatting" |
| Freeze panes | "freeze header row" |
| Protect sheet | "password protect [sheet]" |
Inventory Report:
Financial Dashboard:
Install required packages:
worksheet.addRows() instead of multiple addRow() callsStreaming Large Files:
Data Validation:
Protection:
async function createWithFormulas(data, outputPath) {
const workbook = new ExcelJS.Workbook();
const worksheet = workbook.addWorksheet('Financial Report');
worksheet.columns = [
{ header: 'Month', key: 'month', width: 12 },
{ header: 'Revenue', key: 'revenue', width: 15 },
{ header: 'Expenses', key: 'expenses', width: 15 },
{ header: 'Profit', key: 'profit', width: 15 },
{ header: 'Margin %', key: 'margin', width: 12 }
];
// Add data rows
data.forEach((row, index) => {
const rowIndex = index + 2; // Account for header row
worksheet.addRow({
month: row.month,
revenue: row.revenue,
expenses: row.expenses,
profit: { formula: `B${rowIndex}-C${rowIndex}` }, // Revenue - Expenses
margin: { formula: `D${rowIndex}/B${rowIndex}` } // Profit / Revenue
});
});
// Add totals row
const lastRow = data.length + 2;
worksheet.addRow({
month: 'TOTAL',
revenue: { formula: `SUM(B2:B${lastRow - 1})` },
expenses: { formula: `SUM(C2:C${lastRow - 1})` },
profit: { formula: `SUM(D2:D${lastRow - 1})` },
margin: { formula: `D${lastRow}/B${lastRow}` }
});
// Format totals row
worksheet.getRow(lastRow).font = { bold: true };
worksheet.getRow(lastRow).fill = {
type: 'pattern',
pattern: 'solid',
fgColor: { argb: 'FFE7E6E6' }
};
// Number formatting
worksheet.getColumn('revenue').numFmt = '$#,##0.00';
worksheet.getColumn('expenses').numFmt = '$#,##0.00';
worksheet.getColumn('profit').numFmt = '$#,##0.00';
worksheet.getColumn('margin').numFmt = '0.00%';
await workbook.xlsx.writeFile(outputPath);
}async function addConditionalFormatting(data, outputPath) {
const workbook = new ExcelJS.Workbook();
const worksheet = workbook.addWorksheet('Performance');
// Add data...
worksheet.columns = [
{ header: 'Employee', key: 'name', width: 20 },
{ header: 'Sales', key: 'sales', width: 15 },
{ header: 'Target', key: 'target', width: 15 },
{ header: 'Performance', key: 'performance', width: 15 }
];
data.forEach(row => worksheet.addRow(row));
// Color scale: Green (high) to Red (low)
worksheet.addConditionalFormatting({
ref: 'B2:B100',
rules: [
{
type: 'colorScale',
cfvo: [
{ type: 'min' },
{ type: 'percentile', value: 50 },
{ type: 'max' }
],
color: [
{ argb: 'FFF8696B' }, // Red
{ argb: 'FFFFEB84' }, // Yellow
{ argb: 'FF63BE7B' } // Green
]
}
]
});
// Data bars for performance column
worksheet.addConditionalFormatting({
ref: 'D2:D100',
rules: [
{
type: 'dataBar',
minLength: 0,
maxLength: 100,
color: { argb: 'FF638EC6' }
}
]
});
// Highlight values above target
worksheet.addConditionalFormatting({
ref: 'B2:B100',
rules: [
{
type: 'expression',
formulae: ['B2>C2'], // Sales > Target
style: {
fill: {
type: 'pattern',
pattern: 'solid',
bgColor: { argb: 'FFC6EFCE' }
}
}
}
]
});
await workbook.xlsx.writeFile(outputPath);
}async function createWithChart(data, outputPath) {
const workbook = new ExcelJS.Workbook();
const worksheet = workbook.addWorksheet('Sales');
// Add data
worksheet.columns = [
{ header: 'Month', key: 'month', width: 12 },
{ header: 'Sales', key: 'sales', width: 15 }
];
data.forEach(row => worksheet.addRow(row));
// Create chart (Note: exceljs has limited chart support, consider using xlsx-chart)
// For full chart support, you may need to use Excel templates or officegen library
// Alternative: Add chart using worksheet image
// Or use a charting library to generate image, then embed
await workbook.xlsx.writeFile(outputPath);
}
// For advanced charts, consider using officegen or generating chart imagesasync function createMultiSheetWorkbook(data, outputPath) {
const workbook = new ExcelJS.Workbook();
// Summary sheet
const summary = workbook.addWorksheet('Summary');
summary.columns = [
{ header: 'Metric', key: 'metric', width: 25 },
{ header: 'Value', key: 'value', width: 15 }
];
summary.addRow({ metric: 'Total Sales', value: { formula: "SUM(Details!B:B)" } });
summary.addRow({ metric: 'Average Order', value: { formula: "AVERAGE(Details!B:B)" } });
summary.addRow({ metric: 'Total Orders', value: { formula: "COUNTA(Details!A:A)-1" } });
// Details sheet
const details = workbook.addWorksheet('Details');
details.columns = [
{ header: 'Order ID', key: 'id', width: 12 },
{ header: 'Amount', key: 'amount', width: 15 },
{ header: 'Date', key: 'date', width: 12 }
];
data.forEach(row => details.addRow(row));
// Freeze header row
details.views = [
{ state: 'frozen', xSplit: 0, ySplit: 1 }
];
// Add hyperlink from summary to details
summary.getCell('A1').value = {
text: 'View Details',
hyperlink: '#Details!A1',
tooltip: 'Jump to Details sheet'
};
summary.getCell('A1').font = { color: { argb: 'FF0000FF' }, underline: true };
// Set Summary as active sheet
summary.state = 'visible';
details.state = 'visible';
await workbook.xlsx.writeFile(outputPath);
}const fs = require('fs');
function createCSV(data, outputPath, options = {}) {
const delimiter = options.delimiter || ',';
const headers = options.headers || Object.keys(data[0]);
// Create header row
let csv = headers.join(delimiter) + '\n';
// Add data rows
data.forEach(row => {
const values = headers.map(header => {
let value = row[header] || '';
// Escape quotes and wrap in quotes if contains delimiter or newline
if (typeof value === 'string' && (value.includes(delimiter) || value.includes('\n') || value.includes('"'))) {
value = '"' + value.replace(/"/g, '""') + '"';
}
return value;
});
csv += values.join(delimiter) + '\n';
});
fs.writeFileSync(outputPath, csv, 'utf8');
}worksheet.columns = [
{ header: 'SKU', key: 'sku', width: 15 },
{ header: 'Product', key: 'product', width: 30 },
{ header: 'Quantity', key: 'qty', width: 12 },
{ header: 'Unit Price', key: 'price', width: 15 },
{ header: 'Total Value', key: 'value', width: 15 }
];
data.forEach((item, idx) => {
const row = idx + 2;
worksheet.addRow({
sku: item.sku,
product: item.product,
qty: item.qty,
price: item.price,
value: { formula: `C${row}*D${row}` }
});
});// Summary sheet with KPIs
summary.addRow({ metric: 'Revenue', value: { formula: "SUM(Data!B:B)" } });
summary.addRow({ metric: 'Expenses', value: { formula: "SUM(Data!C:C)" } });
summary.addRow({ metric: 'Net Profit', value: { formula: "B2-B3" } });
summary.addRow({ metric: 'Profit Margin', value: { formula: "B4/B2" } });
summary.getColumn('value').numFmt = '$#,##0.00';npm install exceljs
npm install xlsx # Alternative library
npm install csv-writer # For CSV generationconst workbook = new ExcelJS.stream.xlsx.WorkbookWriter({ filename: outputPath });
const worksheet = workbook.addWorksheet('Large Data');
// Add data in chunks
worksheet.commit();
workbook.commit();worksheet.getCell('A2').dataValidation = {
type: 'list',
allowBlank: true,
formulae: ['"Option1,Option2,Option3"']
};await worksheet.protect('password', {
selectLockedCells: true,
selectUnlockedCells: true
});