技能详情(站内镜像,无评论)
许可证:MIT-0
MIT-0 ·免费使用、修改和重新分发。无需归因。
版本:v2.1.0
统计:⭐ 0 · 696 · 2 current installs · 2 all-time installs
⭐ 0
安装量(当前) 2
🛡 VirusTotal :良性 · OpenClaw :良性
Package:datadrivenconstruction/qto-report
安全扫描(ClawHub)
- VirusTotal :良性
- OpenClaw :良性
OpenClaw 评估
The skill's stated purpose (QTO from BIM/CAD data) matches its instructions and requirements; there are no unexplained credential requests, remote endpoints, or suspicious install steps.
目的
Name/description, required binary (python3) and optional IFC parser (ifcopenshell), and filesystem access are coherent with a QTO/reporting skill that reads BIM exports and produces spreadsheets.
说明范围
SKILL.md contains only local data-processing instructions (pandas-based examples, reading CSV/Excel, applying rules, exporting results). It does not instruct the agent to read unrelated files, call external endpoints, or access secrets.
安装机制
This is an instruction-only skill with no install spec or remote downloads. No archives or third‑party package installs are requested by the skill itself.
证书
The skill requests no environment variables or credentials. The manifest declares filesystem permission which is appropriate for reading user-provided BIM/CAD exports; nothing else is requested.
持久
always is false and the skill is user-invocable. It does not request elevated or persistent platform privileges beyond normal filesystem access declared in claw.json.
综合结论
This skill appears internally consistent for generating QTO reports. Before installing: (1) confirm you trust the skill source/homepage if you plan to supply real project files; (2) ensure python3 and, if you need IFC parsing, ifcopenshell are installed from official sources; (3) do not provide sensitive credentials or unrelated system files—the skill operates on user-provided BIM/CAD exports (CSV/Excel/IFC); (4) test with a small non-sensitiv…
安装(复制给龙虾 AI)
将下方整段复制到龙虾中文库对话中,由龙虾按 SKILL.md 完成安装。
请把本段交给龙虾中文库(龙虾 AI)执行:为本机安装 OpenClaw 技能「Qto Report」。简介:Generate Quantity Take-Off (QTO) reports from BIM/CAD data. Extract volumes, ar…。
请 fetch 以下地址读取 SKILL.md 并按文档完成安装:https://raw.githubusercontent.com/openclaw/skills/refs/heads/main/skills/datadrivenconstruction/qto-report/SKILL.md
(来源:yingzhi8.cn 技能库)
SKILL.md
---
name: "qto-report"
description: "Generate Quantity Take-Off (QTO) reports from BIM/CAD data. Extract volumes, areas, counts by category. Group elements, apply calculation rules, and create cost estimates automatically."
homepage: "https://datadrivenconstruction.io"
metadata: {"openclaw": {"emoji": "⚡", "os": ["win32"], "homepage": "https://datadrivenconstruction.io", "requires": {"bins": ["python3"], "anyBins": ["ifcopenshell"]}}}
---
# Quantity Take-Off (QTO) Report Generation
## Overview
Based on DDC methodology (Chapter 3.2), this skill automates the extraction and grouping of quantities from BIM/CAD data. QTO is the foundation for cost estimation, scheduling, and project planning in construction.
**Book Reference:** "Quantity Take-Off и автоматическое создание смет" / "QTO and Automated Estimates"
> "QTO Quantity Take-Off: группировка данных по атрибутам позволяет автоматически извлекать объемы и количества из BIM-моделей для расчета стоимости."
> — DDC Book, Chapter 3.2
## 5D BIM Concept
The QTO process is central to 5D BIM:
- **3D**: Geometry (volume, area, length)
- **4D**: Time (schedule integration)
- **5D**: Cost (quantity × unit price)
## Quick Start
```python
import pandas as pd
# Load BIM element data
df = pd.read_csv("revit_export.csv")
# Generate QTO by category
qto = df.groupby('Category').agg({
'Volume': 'sum',
'Area': 'sum',
'ElementId': 'count'
}).rename(columns={'ElementId': 'Count'})
# Calculate cost (if unit prices available)
qto['Unit_Price'] = [150, 80, 450, 200] # $/m³
qto['Total_Cost'] = qto['Volume'] * qto['Unit_Price']
qto.to_excel("qto_report.xlsx")
```
## Core QTO Functions
### Basic QTO by Category
```python
import pandas as pd
def generate_qto(df, group_by='Category'):
"""
Generate Quantity Take-Off grouped by specified column
Args:
df: DataFrame with BIM elements
group_by: Column(s) to group by
Returns:
QTO summary DataFrame
"""
# Define aggregations based on available columns
agg_dict = {}
if 'Volume' in df.columns:
agg_dict['Volume'] = 'sum'
if 'Area' in df.columns:
agg_dict['Area'] = 'sum'
if 'Length' in df.columns:
agg_dict['Length'] = 'sum'
if 'Count' in df.columns:
agg_dict['Count'] = 'sum'
else:
agg_dict['ElementId'] = 'count'
qto = df.groupby(group_by).agg(agg_dict)
if 'ElementId' in agg_dict:
qto = qto.rename(columns={'ElementId': 'Count'})
return qto.round(2)
# Usage
qto = generate_qto(df, group_by='Category')
print(qto)
```
### Multi-Level QTO
```python
def generate_multi_level_qto(df):
"""Generate QTO grouped by multiple levels"""
qto = df.groupby(['Level', 'Category', 'Material']).agg({
'Volume': ['sum', 'count'],
'Area': 'sum'
}).round(2)
# Flatten column names
qto.columns = ['Volume_m3', 'Element_Count', 'Area_m2']
# Add percentages
qto['Volume_Pct'] = (qto['Volume_m3'] /
qto['Volume_m3'].sum() * 100).round(1)
return qto.sort_values('Volume_m3', ascending=False)
# Usage
qto = generate_multi_level_qto(df)
qto.to_excel("qto_multi_level.xlsx")
```
### QTO with Pivot Table
```python
def generate_qto_pivot(df, values='Volume', index='Level', columns='Category'):
"""Generate QTO as pivot table"""
pivot = pd.pivot_table(
df,
values=values,
index=index,
columns=columns,
aggfunc='sum',
fill_value=0,
margins=True,
margins_name='TOTAL'
).round(2)
return pivot
# Usage - Volume by Level and Category
qto_pivot = generate_qto_pivot(df, values='Volume')
qto_pivot.to_excel("qto_pivot.xlsx")
```
## Cost Calculation from QTO
### Apply Unit Prices
```python
def calculate_cost_from_qto(qto_df, prices_df, quantity_col='Volume'):
"""
Calculate costs by applying unit prices to quantities
Args:
qto_df: QTO DataFrame with quantities
prices_df: DataFrame with Category and Unit_Price
quantity_col: Column containing quantities
"""
# Merge with prices
result = qto_df.reset_index().merge(
prices_df, on='Category', how='left'
)
# Calculate costs
result['Total_Cost'] = result[quantity_col] * result['Unit_Price']
result['Cost_Pct'] = (result['Total_Cost'] /
result['Total_Cost'].sum() * 100).round(1)
# Summary
grand_total = result['Total_Cost'].sum()
print(f"Grand Total: ${grand_total:,.2f}")
return result
# Unit prices database
prices = pd.DataFrame({
'Category': ['Wall', 'Floor', 'Column', 'Beam', 'Foundation'],
'Unit_Price': [150, 80, 450, 200, 120], # $/m³
'Unit': ['m³', 'm³', 'm³', 'm³', 'm³']
})
# Calculate
cost_estimate = calculate_cost_from_qto(qto, prices)
cost_estimate.to_excel("cost_estimate.xlsx", index=False)
```
### Apply Rules from Excel
```python
def apply_excel_rules(df, rules_path):
"""
Apply calculation rules defined in Excel file
Excel format:
| Category | Formula_Type | Factor | Unit |
| Wall | volume | 1.05 | m³ |
| Floor | area | 1.10 | m² |
"""
rules = pd.read_excel(rules_path)
results = []
for _, rule in rules.iterrows():
category = rule['Category']
formula_type = rule['Formula_Type']
factor = rule['Factor']
category_data = df[df['Category'] == category].copy()
if formula_type == 'volume':
category_data['Quantity'] = category_data['Volume'] * factor
elif formula_type == 'area':
category_data['Quantity'] = category_data['Area'] * factor
elif formula_type == 'length':
category_data['Quantity'] = category_data['Length'] * factor
elif formula_type == 'count':
category_data['Quantity'] = category_data.groupby('Category').ngroup() + 1
category_data['Unit'] = rule['Unit']
results.append(category_data)
return pd.concat(results, ignore_index=True)
# Usage
df_with_quantities = apply_excel_rules(df, "calculation_rules.xlsx")
```
## BIM Data Extraction Patterns
### From Revit Export (CSV)
```python
def process_revit_export(csv_path):
"""Process standard Revit schedule export"""
df = pd.read_csv(csv_path)
# Standardize column names
column_mapping = {
'Family and Type': 'Type',
'Volume': 'Volume',
'Area': 'Area',
'Count': 'Count',
'Level': 'Level',
'Category': 'Category'
}
df = df.rename(columns={
k: v for k, v in column_mapping.items()
if k in df.columns
})
# Convert volume from cubic feet to cubic meters (if needed)
if 'Volume' in df.columns:
# Revit exports in cubic feet by default
df['Volume_m3'] = df['Volume'] * 0.0283168
return df
# Usage
df = process_revit_export("revit_schedule.csv")
qto = generate_qto(df)
```
### From IFC Export
```python
# Using IfcOpenShell
import ifcopenshell
import pandas as pd
def extract_qto_from_ifc(ifc_path):
"""Extract quantities from IFC file"""
ifc = ifcopenshell.open(ifc_path)
elements = []
for element in ifc.by_type("IfcBuildingElement"):
# Get properties
props = {
'GlobalId': element.GlobalId,
'Name': element.Name,
'Type': element.is_a(),
'Material': None,
'Volume': None,
'Area': None
}
# Extract quantities from property sets
for definition in element.IsDefinedBy:
if definition.is_a('IfcRelDefinesByProperties'):
pset = definition.RelatingPropertyDefinition
if pset.is_a('IfcElementQuantity'):
for qty in pset.Quantities:
if qty.is_a('IfcQuantityVolume'):
props['Volume'] = qty.VolumeValue
elif qty.is_a('IfcQuantityArea'):
props['Area'] = qty.AreaValue
elements.append(props)
return pd.DataFrame(elements)
# Usage
df = extract_qto_from_ifc("model.ifc")
qto = generate_qto(df, group_by='Type')
```
## Advanced QTO Reports
### Detailed Material Breakdown
```python
def material_breakdown_qto(df):
"""Detailed breakdown by material type"""
breakdown = df.groupby(['Category', 'Material', 'Type']).agg({
'Volume': 'sum',
'Area': 'sum',
'ElementId': 'nunique'
}).rename(columns={'ElementId': 'Unique_Elements'})
# Add subtotals for each category
category_totals = df.groupby('Category').agg({
'Volume': 'sum',
'Area': 'sum'
})
breakdown['Category_Volume_Pct'] = breakdown.apply(
lambda row: (row['Volume'] /
category_totals.loc[row.name[0], 'Volume'] * 100),
axis=1
).round(1)
return breakdown
# Usage
material_qto = material_breakdown_qto(df)
material_qto.to_excel("material_breakdown.xlsx")
```
### QTO with Waste Factors
```python
def qto_with_waste(df, waste_factors):
"""
Apply waste factors to quantities
Args:
waste_factors: dict like {'Concrete': 1.05, 'Steel': 1.03}
"""
qto = df.groupby(['Category', 'Material']).agg({
'Volume': 'sum'
}).reset_index()
# Apply waste factors
qto['Waste_Factor'] = qto['Material'].map(waste_factors).fillna(1.0)
qto['Net_Volume'] = qto['Volume']
qto['Gross_Volume'] = qto['Volume'] * qto['Waste_Factor']
qto['Waste_Volume'] = qto['Gross_Volume'] - qto['Net_Volume']
return qto
# Usage
waste = {'Concrete': 1.05, 'Brick': 1.08, 'Steel': 1.03}
qto = qto_with_waste(df, waste)
```
### QTO Comparison (Design vs As-Built)
```python
def compare_qto(design_df, asbuilt_df, group_by='Category'):
"""Compare designed vs as-built quantities"""
design_qto = design_df.groupby(group_by)['Volume'].sum()
asbuilt_qto = asbuilt_df.groupby(group_by)['Volume'].sum()
comparison = pd.DataFrame({
'Design': design_qto,
'AsBuilt': asbuilt_qto
})
comparison['Difference'] = comparison['AsBuilt'] - comparison['Design']
comparison['Variance_%'] = (
(comparison['AsBuilt'] - comparison['Design']) /
comparison['Design'] * 100
).round(1)
return comparison
# Usage
comparison = compare_qto(design_df, asbuilt_df)
print(comparison)
```
## Export Functions
### Export to Multiple Formats
```python
def export_qto_report(qto_df, base_name, include_charts=True):
"""Export QTO to Excel with formatting and charts"""
from openpyxl import Workbook
from openpyxl.chart import BarChart, Reference
# Excel with multiple sheets
with pd.ExcelWriter(f"{base_name}.xlsx", engine='openpyxl') as writer:
# Summary sheet
qto_df.to_excel(writer, sheet_name='Summary')
# Detailed data
if hasattr(qto_df, 'reset_index'):
qto_df.reset_index().to_excel(
writer, sheet_name='Details', index=False
)
# CSV for integration
qto_df.to_csv(f"{base_name}.csv")
# JSON for API
qto_df.reset_index().to_json(
f"{base_name}.json", orient='records', indent=2
)
print(f"Exported: {base_name}.xlsx, .csv, .json")
# Usage
export_qto_report(qto, "project_qto")
```
## Quick Reference
| Task | Code |
|------|------|
| Basic QTO | `df.groupby('Category')['Volume'].sum()` |
| Multi-column QTO | `df.groupby(['Level', 'Category']).agg({...})` |
| Pivot QTO | `pd.pivot_table(df, values='Volume', ...)` |
| Apply prices | `qto.merge(prices, on='Category')` |
| Calculate cost | `df['Cost'] = df['Volume'] * df['Unit_Price']` |
| Add waste factor | `df['Gross'] = df['Net'] * waste_factor` |
## Resources
- **Book**: "Data-Driven Construction" by Artem Boiko, Chapter 3.2
- **Website**: https://datadrivenconstruction.io
- **IfcOpenShell**: https://ifcopenshell.org
## Next Steps
- See `cost-estimation-resource` for detailed cost calculations
- See `auto-estimate-generator` for automated estimate creation
- See `gantt-chart` for 4D scheduling integration
- See `co2-estimation` for carbon footprint calculations