Working with Excel
pyetm provides comprehensive Excel import/export functionality for managing scenario data. This allows you to work with scenarios in bulk via spreadhseets.
Excel Input File Structure
pyetm uses a standardized Excel format with multiple sheets:
| Sheet Name | Contents | Optional? |
|---|---|---|
MAIN |
Scenario metadata (ID, title, area, end year, etc.) | |
EXPORT_CONFIG |
Export configuration for scenario(s) | |
USERS |
User access permissions for scenarios | optional |
INPUTS |
User values for each scenario | optional |
SORTABLES |
Technology ordering (merit order, heat network) | optional - flexible name |
CUSTOM_CURVES |
Custom curves for specific or multiple scenarios | optional - flexible name |
MAIN Sheet Fields
The MAIN sheet contains scenario metadata with the following fields:
| Field | Type | Description | Example |
|---|---|---|---|
short_name |
String | Short identifier for the scenario | BASE |
scenario_id |
Integer | Saved scenario ID (if loading existing) | 123456 |
session |
Boolean | If true, indicates you are working with sessions, for example scenario_id now refers to a session_id (defaults to false) | TRUE |
copy_from |
Integer | ID of scenario to copy from | 111111 |
title |
String | Scenario name | My Scenario |
area_code |
String | Dataset area code (also indicates start year) | nl2023 |
end_year |
Integer | Future year for the scenario | 2050 |
private |
Boolean | Whether scenario is private | true, false |
custom_curves |
String | Name of custom curves sheet | CUSTOM_CURVES |
sortables |
String | Name of sortables sheet | SORTABLES |
EXPORT_CONFIG Sheet Structure
| Field Name | Valid Values | Description | Example |
|---|---|---|---|
include_inputs (or inputs) |
true, false, yes, no, 1, 0 |
Export slider input values | true |
include_sortables (or sortables) |
true, false, yes, no, 1, 0 |
Export technology ordering | true |
include_custom_curves (or custom_curves) |
true, false, yes, no, 1, 0 |
Export custom price/demand curves | true |
include_gqueries (or gquery_results, gqueries) |
true, false, yes, no, 1, 0 |
Export query results | true |
hourly_curves |
true, false, OR comma-separated carriers |
Controls hourly curve exports (see below) | electricity, heat |
annual_exports |
true, false, OR comma-separated types |
Annual export types to include (see below) | energy_flow, sankey |
include_input_defaults (or defaults) |
true, false |
Include default input values (not just user-set) | false |
include_input_min_max (or min_max) |
true, false |
Include min/max bounds for inputs | true |
Hourly Curves Options
The hourly_curves field has three modes:
-
Export all carriers (set to
Exports curves for:true):electricity,hydrogen,heat,methane -
No hourly curves (set to
false): -
Specific carriers or curves (comma-separated list):
Or specify individual curve names:
Available carrier types:
electricity- Maps to ETM: `merit_order``heat- Maps to ETM:heat_networkhydrogen- Maps to ETM:hydrogen,methane- Maps to ETM:network_gas
Available curve names (can be specified individually):
merit_order, electricity_price, heat_network, agriculture_heat, household_heat, buildings_heat, hydrogen, network_gas, residual_load, hydrogen_integral_cost
Validation
Invalid carrier or curve names will be filtered out with a warning. Only valid entries will be exported.
Annual Exports Options
The annual_exports field has three modes:
-
Export all types (set to
Exports all 7 available types (see below)true): -
No annual exports (set to
false): -
Specific export types (comma-separated list):
Available export types:
production_parameters- Production parameters for technologiesenergy_flow- Energy flow data between nodesenergy_flow_present- Present-year energy flow datamolecule_flow- Molecule flow datasankey- Sankey diagram datastorage_parameters- Storage parameters for technologiescosts_parameters- Cost parameters for technologies
Validation
Invalid export type names will be filtered out with a warning. Only valid entries will be exported.
Input Sheet Structures
This section documents the expected format for optional input sheets. All sheets are optional - include only the ones you need.
SLIDER_SETTINGS Sheet
Purpose: Set input values (slider settings) for your scenarios.
Structure:
input_key | scenario_1 | scenario_2 | scenario_3 |
---------------------------------------------|------------|------------|------------|
households_number_of_inhabitants | 17000000 | 18000000 | 16500000 |
households_insulation_level | 1.5 | 2.0 | 1.2 |
transport_car_using_electricity_share | 25 | 40 | 30 |
- Column 1: Input keys (learn about available keys in the Inputs documentation)
- Remaining columns: Scenario identifiers (short_name from MAIN sheet)
- Values: User values to set for each slider
Notes:
- Column headers must match the
short_namevalues from your MAIN sheet - Leave cells empty to keep default values
- See
Scenario.update_user_values()for programmatic equivalent
USERS Sheet
Purpose: Define user access permissions for scenarios.
Structure:
email | scenario_1 | scenario_2 | scenario_3 |
-----------------------|-------------|-------------|-------------|
user1@example.com | owner | viewer | |
user2@example.com | collabor. | owner | viewer |
admin@example.com | owner | owner | owner |
- Column 1: User email addresses
- Remaining columns: Scenario identifiers (short_name from MAIN sheet)
-
Valid roles:
-
owner- Full control over the scenario collaborator- Can edit the scenarioviewer- Read-only access
Notes:
- Empty cells mean the user has no access to that scenario
- See
Scenario.update_users()for programmatic equivalent
GQUERIES Sheet
Purpose: Specify GQL queries to execute for all scenarios.
Structure:
dashboard_total_costs
dashboard_co2_emissions
dashboard_renewable_percentage
final_demand_of_electricity
- Format: Single column, no header
- Content: One query key per row
- Results: Exported to
GQUERIES_RESULTSsheet
Notes:
- Find available queries in the GQueries documentation
- Whitespace is automatically trimmed
- See
Scenario.add_queries()for programmatic equivalent
SORTABLES Sheet
Purpose: Define technology ordering (e.g., merit order for electricity dispatch, heat network priority).
Structure:
electricity_merit_order | heat_network |
-------------------------------------------|---------------------------------------|
energy_power_wind_turbine_inland | energy_heat_burner_hydrogen |
energy_power_solar_pv_solar_radiation | energy_heat_heatpump_water_water_ts...|
energy_power_nuclear_gen3_uranium_oxide | energy_heat_burner_network_gas |
energy_power_ultra_supercritical_coal | |
- Column headers: Sortable names (e.g.,
electricity_merit_order,heat_network) - Rows: Technology keys in priority order (top = highest priority)
- Multiple sortables: Add more columns for different sortable types
Notes:
- Can be applied to one or multiple scenarios via MAIN sheet's
sortablescolumn - Technologies listed first have highest priority in dispatch/ordering
- See
Scenario.set_sortables_from_dataframe()for programmatic equivalent
CUSTOM_CURVES Sheet
Purpose: Upload custom hourly price or demand curves (8760 hours per year).
Structure:
electricity_price | hydrogen_demand | solar_capacity |
------------------|-----------------|----------------|
45.2 | 100.5 | 1200.0 |
46.1 | 105.2 | 1180.5 |
47.3 | 98.7 | 1250.3 |
... | ... | ... |
(8760 rows total)
- Column headers: Curve names (define custom names for your curves)
- Rows: Hourly values for the full year (exactly 8760 rows required)
- Values: Numeric data for each hour
Notes:
- Must have exactly 8760 rows (one per hour of the year)
- Can be applied to one or multiple scenarios via MAIN sheet's
custom_curvescolumn - Data is validated before upload to ensure correct length
- See
Scenario.update_custom_curves()for programmatic equivalent
Important Notes
Scenario References:
- SLIDER_SETTINGS and USERS use
short_namefrom MAIN sheet as column headers - SORTABLES and CUSTOM_CURVES can be referenced from MAIN sheet's
sortablesandcustom_curvescolumns - This allows different scenarios to use different configurations
Update Behavior:
When using from_excel():
update=False- Load data locally only, don't upload to ETMupdate=True- Upload all changes to ETM (inputs, users, sortables, custom curves)update=["user_values"]- Selective upload (only user values)
From Excel
Import scenarios from an Excel file without uploading to the API:
from pyetm import Scenarios
# Load/create scenarios locally (default: update=False)
scenarios = Scenarios.from_excel("../examples/excel/my_scenarios.xlsx")
Update Default is False
By default, update=False to prevent accidental API modifications. Always explicitly set update=True or pass a list when you want to upload changes.
Import with the Update Parameter
The update parameter controls whether data is uploaded to the API:
from pyetm import Scenarios
# Option 1: Load locally only (default)
scenarios = Scenarios.from_excel("scenarios.xlsx", update=False)
# Data is loaded into Python objects but NOT uploaded to ETM API
# Option 2: Upload all data types
scenarios = Scenarios.from_excel("scenarios.xlsx", update=True)
# Uploads: user_values, custom_curves, sortables, users to the ETM API
# Option 3: Upload specific data types only
scenarios = Scenarios.from_excel(
"scenarios.xlsx",
update=["user_values", "sortables"]
)
# Only uploads user_values and sortables, skips custom_curves and users
Available update types:
- "user_values" - Slider input values
- "custom_curves" - Custom price/demand curves
- "sortables" - Technology ordering
- "users" - User access permissions (Scenario only, not Session)
Import with ScenarioPacker
For advanced control, use ScenarioPacker directly:
from pyetm.models import ScenarioPacker
# Load Excel into packer
packer = ScenarioPacker.from_excel("scenarios.xlsx")
# Access structured data
main_info = packer.main_info() # DataFrame with scenario metadata
inputs_df = packer.inputs(columns="user") # User values as DataFrame
sortables_df = packer.sortables() # Sortables as DataFrame
# Access scenarios
scenarios = packer.scenarios
Export Configuration
Control what data is exported using ExportConfig:
from pyetm import Scenario
from pyetm.models import ExportConfig
# Create a scenario
scenario = Scenario.new(
title="Export Example",
area_code="nl",
end_year=2050
)
# Configure exports
config = ExportConfig(
include_inputs=True, # Include input values
include_sortables=True, # Include technology ordering
include_custom_curves=False, # Skip custom curves
include_gqueries=True, # Include query results
include_users=True, # Include user permissions
include_input_defaults=False, # Don't include default values
include_input_min_max=True, # Include min/max bounds
hourly_curves=["electricity", "heat"], # Hourly curves for these carriers
include_annual_exports=["energy_flow", "sankey"] # Annual exports
)
# Set configuration on scenario
scenario.set_export_config(config)
# Later retrieve the config
current_config = scenario.get_export_config()
ExportConfig Options
| Parameter | Type | Description |
|---|---|---|
include_inputs |
bool |
Export slider input values |
include_sortables |
bool |
Export technology ordering |
include_custom_curves |
bool |
Export custom curves |
include_gqueries |
bool |
Export query results |
include_users |
bool |
Export user permissions |
include_input_defaults |
bool |
Include default input values (not just user-set) |
include_input_min_max |
bool |
Include min/max bounds for inputs |
hourly_curves |
List[str] |
Hourly curves for carriers: "electricity", "heat", "hydrogen", "methane" |
include_annual_exports |
List[str] |
Annual exports: "energy_flow", "sankey", "production_parameters", etc. |
To Excel
Basic Export
Export a single scenario to Excel:
from pyetm import Scenario
# Load or create a scenario
scenario = Scenario.load(123456)
# Export with default settings
scenario.to_excel("my_scenario.xlsx")
Export Multiple Scenarios
Export a collection of scenarios to a single file:
from pyetm import Scenario, Scenarios
# Create multiple scenarios
scenario_1 = Scenario.load(111111)
scenario_2 = Scenario.load(222222)
scenario_3 = Scenario.load(333333)
# Create collection
scenarios = Scenarios(items=[scenario_1, scenario_2, scenario_3])
# Export all to one file
scenarios.to_excel("comparison.xlsx")
Export with Options
Customize what data is exported:
from pyetm import Scenario
scenario = Scenario.load(123456)
# Export specific data types and carriers
scenario.to_excel(
"custom_export.xlsx",
hourly_curves=["electricity", "heat"], # Only electricity and heat hourly curves
include_inputs=True, # Include inputs
include_sortables=True, # Include sortables
include_custom_curves=False, # Skip custom curves
include_gqueries=True, # Include query results
include_hourly_curves=True, # Include hourly curves
include_input_defaults=True, # Include default input values
include_input_min_max=True, # Include min/max bounds
include_users=False, # Skip user permissions
include_annual_exports=["energy_flow", "sankey"] # Include specific annual exports
)
Export with ScenarioPacker
Use ScenarioPacker for advanced export control:
from pyetm.models import ScenarioPacker
# Create packer and add scenarios
packer = ScenarioPacker()
packer.add(scenario_1, scenario_2, scenario_3)
# Add specific data types
packer.add_inputs(scenario_1, scenario_2)
packer.add_sortables(scenario_1)
packer.add_hourly_output_curves(scenario_2, carrier_type="electricity")
packer.add_annual_exports(scenario_3, exports=["energy_flow"])
# Export
packer.to_excel(
"advanced_export.xlsx",
hourly_curves=["electricity"],
include_inputs=True,
include_annual_exports=["energy_flow", "sankey"]
)