Chapter 4: From Script to Tool

Translating ABAP selection-screen thinking into Python parameters and user input

Chapter Goal

Give the User Control

In Chapter 3, the report was useful, but it still had one major limitation: the filter was hardcoded in the script. That means the developer controls the report instead of the user.

ABAP developers already know this problem. That is why ABAP reports often use PARAMETERS and SELECT-OPTIONS. In this chapter, we recreate that idea in Python.

HardcodedFilter lives in code
PromptAsk user while running
ArgumentPass value at runtime
ValidateHandle bad input
ReportGenerate output
Big idea: A script becomes a tool when the user can control it without editing the source code.

The ABAP Pattern: Selection Screen

In ABAP, you might let the user choose material type and plant before the report runs.

ABAP Example

PARAMETERS: p_mtart TYPE mtart DEFAULT 'FERT', p_plant TYPE werks_d DEFAULT '1000'. SELECT matnr, maktx, mtart, plant, stock FROM zmaterial_stock INTO TABLE @DATA(lt_materials) WHERE mtart = @p_mtart AND plant = @p_plant.

What users understand

Selection Screen Preview
Execute Report
Python translation: We can start with simple terminal input, then move to command-line arguments, and later to a real web form.

Option 1: Ask the User with input()

The simplest way to get user input in Python is the built-in input() function. This is not fancy, but it is easy to understand.

material_type = input("Enter material type, for example FERT: ") plant = input("Enter plant, for example 1000: ") filtered_df = df[ (df["mtart"] == material_type) & (df["plant"].astype(str) == plant) ]

Expected terminal behavior

Terminal Preview
Enter material type, for example FERT: FERT Enter plant, for example 1000: 1000 Report generated for: Material Type: FERT Plant: 1000

Use input() when you are learning, prototyping, or building a small tool for yourself. For shared tools, command-line arguments or a web form are usually better.

Option 2: Use Command-Line Arguments

Command-line arguments let the user provide values when launching the script. This is closer to running a report with predefined parameters.

python material_report.py --mtart FERT --plant 1000

Python has a built-in module named argparse for this.

import argparse parser = argparse.ArgumentParser( description="Generate a material report." ) parser.add_argument( "--mtart", default="FERT", help="Material type filter, for example FERT or HALB" ) parser.add_argument( "--plant", default="1000", help="Plant filter, for example 1000" ) args = parser.parse_args() material_type = args.mtart plant = args.plant

Expected terminal behavior

Terminal Preview
C:\dev\think-like-python> python material_report.py --mtart FERT --plant 1000 Loaded 6 material records. Applied filters: Material Type: FERT Plant: 1000 Generated: material_report.html filtered_materials.xlsx
Practical value: Command-line parameters make your script easier to reuse, schedule, document, and automate.

ABAP SELECT-OPTIONS vs Multiple Values

ABAP developers often use SELECT-OPTIONS when users need ranges or multiple values. In Python, a simple beginner version is to accept a comma-separated list.

ABAP

SELECT-OPTIONS: s_mtart FOR mara-mtart. SELECT matnr, mtart, plant FROM mara INTO TABLE @DATA(lt_materials) WHERE mtart IN @s_mtart.

Python

parser.add_argument( "--mtart", default="FERT", help="Comma-separated material types" ) material_types = args.mtart.split(",") filtered_df = df[df["mtart"].isin(material_types)]

Example command

python material_report.py --mtart FERT,HALB --plant 1000

This is not a full SELECT-OPTIONS replacement yet. It does not handle ranges, exclusions, or complex operators. But it is enough to introduce the idea of user-controlled filtering.

Validate User Input

Once users control inputs, they can also enter values that do not exist. Your script should respond clearly instead of failing silently.

if filtered_df.empty: print("No records found for the selected filters.") print(f"Material Type: {material_type}") print(f"Plant: {plant}") exit()

Expected “no records” behavior

Terminal Preview
C:\dev\think-like-python> python material_report.py --mtart FERT --plant 9999 No records found for the selected filters. Material Type: FERT Plant: 9999
Common mistake: Do not assume users will enter valid values. Good tools explain what happened.

Full Script: Parameterized Material Report

This version builds on Chapter 3. It accepts material type and plant as runtime parameters. Save it as material_report_parameters.py.

import argparse import pandas as pd from bokeh.io import output_file, save from bokeh.layouts import column from bokeh.models import ColumnDataSource, DataTable, TableColumn, Div from bokeh.plotting import figure # 1. Define command-line arguments parser = argparse.ArgumentParser( description="Generate an ALV-style material report with Python." ) parser.add_argument( "--mtart", default="FERT", help="Comma-separated material types. Example: FERT,HALB" ) parser.add_argument( "--plant", default="1000", help="Plant filter. Example: 1000" ) args = parser.parse_args() material_types = [value.strip() for value in args.mtart.split(",")] plant = args.plant.strip() # 2. Load data df = pd.read_csv("materials.csv") print(f"Loaded {len(df)} material records.") # 3. Apply filters filtered_df = df[ (df["mtart"].isin(material_types)) & (df["plant"].astype(str) == plant) ] if filtered_df.empty: print("No records found for the selected filters.") print(f"Material Types: {material_types}") print(f"Plant: {plant}") exit() # 4. Sort result filtered_df = filtered_df.sort_values(by="stock", ascending=False) # 5. Export to Excel excel_file = "filtered_materials.xlsx" filtered_df.to_excel(excel_file, index=False) # 6. Build Bokeh table source = ColumnDataSource(filtered_df) columns = [ TableColumn(field="matnr", title="Material"), TableColumn(field="maktx", title="Description"), TableColumn(field="mtart", title="Type"), TableColumn(field="plant", title="Plant"), TableColumn(field="stock", title="Stock") ] table = DataTable( source=source, columns=columns, width=950, height=280, sortable=True ) # 7. Build chart counts = filtered_df["mtart"].value_counts() chart = figure( x_range=list(counts.index), title="Filtered Material Count by Type", height=350, width=700 ) chart.vbar( x=list(counts.index), top=list(counts.values), width=0.6 ) # 8. Save browser report html_file = "material_report.html" title = Div( text=f\"\"\" <h2>Material Report</h2> <p>Material Types: {", ".join(material_types)} | Plant: {plant}</p> <p>Excel export created: {excel_file}</p> \"\"\" ) output_file(html_file) save(column(title, table, chart)) print("Report generated successfully.") print(f"HTML report: {html_file}") print(f"Excel export: {excel_file}")

In Chapter 3, show() immediately opened the browser. In this chapter, output_file() and save() create an HTML file that can be shared or uploaded somewhere later.

What You Should See

⌨️
Command

python material_report_parameters.py --mtart FERT --plant 1000

🌐
HTML Report

A browser report named material_report.html.

📊
Excel Export

A filtered Excel file named filtered_materials.xlsx.

Expected browser preview

material_report.html

Material Report

Material Types: FERT | Plant: 1000

Material Description Type Plant Stock
1006Demo Finished Product 3FERT100067
1001Demo Finished ProductFERT100045

Folder Structure

By now, your folder should look something like this:

think-like-python-project/ │ ├── material_report_parameters.py ├── materials.csv ├── material_report.html ← generated ├── filtered_materials.xlsx ← generated └── requirements.txt
pandas bokeh openpyxl

Try This

parser.add_argument( "--min-stock", type=int, default=0, help="Minimum stock quantity" ) # Later in the filter: filtered_df = filtered_df[filtered_df["stock"] >= args.min_stock]

Chapter 4 Checkpoint

Next: Now that the script behaves more like a tool, the next step is to give it a real interface. Chapter 5 can introduce a simple Flask web app with a form that replaces the command line.
End of Chapter 4