← All skills
Tencent SkillHub · Data Analysis

Qto Report

Generate Quantity Take-Off (QTO) reports from BIM/CAD data. Extract volumes, areas, counts by category. Group elements, apply calculation rules, and create c...

skill openclawclawhub Free
0 Downloads
0 Stars
0 Installs
0 Score
High Signal

Generate Quantity Take-Off (QTO) reports from BIM/CAD data. Extract volumes, areas, counts by category. Group elements, apply calculation rules, and create c...

⬇ 0 downloads ★ 0 stars Unverified but indexed

Install for OpenClaw

Quick setup
  1. Download the package from Yavira.
  2. Extract the archive and review SKILL.md first.
  3. Import or place the package into your OpenClaw setup.

Requirements

Target platform
OpenClaw
Install method
Manual import
Extraction
Extract archive
Prerequisites
OpenClaw
Primary doc
SKILL.md

Package facts

Download mode
Yavira redirect
Package format
ZIP package
Source platform
Tencent SkillHub
What's included
claw.json, instructions.md, SKILL.md

Validation

  • Use the Yavira download entry.
  • Review SKILL.md after the package is downloaded.
  • Confirm the extracted package contains the expected setup assets.

Install with your agent

Agent handoff

Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.

  1. Download the package from Yavira.
  2. Extract it into a folder your agent can access.
  3. Paste one of the prompts below and point your agent at the extracted folder.
New install

I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Tell me what you changed and call out any manual steps you could not complete.

Upgrade existing

I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Summarize what changed and any follow-up checks I should run.

Trust & source

Release facts

Source
Tencent SkillHub
Verification
Indexed source record
Version
2.1.0

Documentation

ClawHub primary doc Primary doc: SKILL.md 17 sections Open source page

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

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")

Basic QTO by Category

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

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

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")

Apply Unit Prices

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

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")

From Revit Export (CSV)

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

# 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')

Detailed Material Breakdown

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

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)

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 to Multiple Formats

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

TaskCodeBasic QTOdf.groupby('Category')['Volume'].sum()Multi-column QTOdf.groupby(['Level', 'Category']).agg({...})Pivot QTOpd.pivot_table(df, values='Volume', ...)Apply pricesqto.merge(prices, on='Category')Calculate costdf['Cost'] = df['Volume'] * df['Unit_Price']Add waste factordf['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

Category context

Data access, storage, extraction, analysis, reporting, and insight generation.

Source: Tencent SkillHub

Largest current source with strong distribution and engagement signals.

Package contents

Included in package
2 Docs1 Config
  • SKILL.md Primary doc
  • instructions.md Docs
  • claw.json Config