Skip to main content

Lesson 07: Strings (Text and Labels)

Learn Python strings for BIM automation: rename sheets, clean room names, format titles, and control text that drives efficient architectural workflows.

Introduction

Architects work with text constantly. Room names, sheet numbers, view names, file paths, drawing titles.

If you've ever renamed 200 sheets by hand, or spent an hour fixing inconsistent room names, you know the pain.

In Python, text is called a string. Strings are how you handle names, labels, and any text-based information.

This lesson is critical. Most BIM automation involves manipulating strings — reading them, combining them, extracting parts, and reformatting them.

By the end of this lesson, you'll see why strings are the most useful data type for architectural workflows.


Lesson Overview

This section contains a general overview of topics you will learn in this lesson.

  • Understand what strings are and how to create them
  • Learn to combine strings (concatenation)
  • Extract parts of strings (slicing)
  • Change string case (upper, lower, title)
  • Find and replace text in strings
  • Use string methods for real BIM tasks
  • Avoid common string errors

What Is a String?

A string is text enclosed in quotes.

room_name = "Conference Room"
sheet_number = "A-101"
file_path = "C:/Projects/2024-001/Floor Plans.pdf"

You can use single quotes or double quotes. Python treats them the same.

room_name = "Conference Room"   # Double quotes
room_name = 'Conference Room'   # Single quotes (same result)

Why Both Quote Types Exist

Sometimes your text contains quotes. Having both types makes this easier.

# Text with an apostrophe
note = "Client's requirements changed"  # Double quotes work

# Or
note = 'Client\\'s requirements changed'  # Escape the apostrophe with \\

# Text with double quotes inside
message = 'The room is called "Main Conference"'

Use whichever makes your string clearer.


Creating Strings

# Simple strings
project_name = "Community Center"
architect = "Smith & Associates"
status = "In Progress"

# Empty string
description = ""

# Multi-line strings (use triple quotes)
notes = """
This is a multi-line string.
It can span several lines.
Useful for long descriptions.
"""

Combining Strings (Concatenation)

Use the + operator to join strings.

discipline = "A"
sheet_number = "101"
full_number = discipline + "-" + sheet_number

print(full_number)  # Output: A-101

Architectural Example: Sheet Naming

discipline = "A"
sheet_type = "Floor Plan"
level = "Level 02"
revision = "R03"

# Build the full sheet name
sheet_name = discipline + " - " + sheet_type + " - " + level + " - " + revision

print(sheet_name)
# Output: A - Floor Plan - Level 02 - R03

Common Mistake: Concatenating Strings and Numbers

You can't directly concatenate strings and numbers.

floor_number = 2
floor_name = "Level " + floor_number
# Error: TypeError: can only concatenate str (not "int") to str

Convert the number to a string first using str().

floor_number = 2
floor_name = "Level " + str(floor_number)

print(floor_name)  # Output: Level 2

Architectural Example: Room Numbering

room_type = "Conference Room"
room_number = 201

# Convert number to string before concatenating
full_name = room_type + " " + str(room_number)

print(full_name)  # Output: Conference Room 201

String Length

Find how many characters are in a string using len().

sheet_name = "A-101"
name_length = len(sheet_name)

print(name_length)  # Output: 5

Why This Matters

# Check if sheet number is the correct format
sheet_number = "A-101"

if len(sheet_number) == 5:
    print("Sheet number format is correct")
else:
    print("Sheet number format is wrong")

String Indexing (Accessing Individual Characters)

Each character in a string has a position (index). Python starts counting at 0.

sheet_number = "A-101"
#               0 1 2 3 4  (index positions)

first_char = sheet_number[0]
print(first_char)  # Output: A

last_char = sheet_number[4]
print(last_char)  # Output: 1

Negative Indexing

You can count from the end using negative numbers.

sheet_number = "A-101"

last_char = sheet_number[-1]
print(last_char)  # Output: 1

second_last = sheet_number[-2]
print(second_last)  # Output: 0

String Slicing (Extracting Parts)

Extract a portion of a string using [start:end].

sheet_number = "A-101"

# Get discipline (first character)
discipline = sheet_number[0]
print(discipline)  # Output: A

# Get number part (characters 2 to end)
number = sheet_number[2:]
print(number)  # Output: 101

# Get first three characters
prefix = sheet_number[0:3]
print(prefix)  # Output: A-1

Slicing Rules

  • [start:end] — from start up to (but not including) end
  • [start:] — from start to the end
  • [:end] — from beginning up to (but not including) end
  • [:] — entire string (useful for copying)

Architectural Example: Extracting Discipline from Sheet Number

sheet_numbers = ["A-101", "S-201", "M-301", "E-401"]

for sheet in sheet_numbers: # We'll learn about for loops in the coming lessons.
    discipline = sheet[0]
    print("Discipline:", discipline)

# Output:
# Discipline: A
# Discipline: S
# Discipline: M
# Discipline: E

String Methods

Strings come with built-in methods (functions) that perform common operations.

Changing Case

project_name = "community center"

# Make all uppercase
upper_name = project_name.upper()
print(upper_name)  # Output: COMMUNITY CENTER

# Make all lowercase
lower_name = project_name.lower()
print(lower_name)  # Output: community center

# Title case (first letter of each word capitalized)
title_name = project_name.title()
print(title_name)  # Output: Community Center

Architectural Use Case: Standardising Room Names

# Room names from different sources have inconsistent capitalization
rooms = ["conference room", "MEETING ROOM", "break Room"]

# Standardize to title case
standardized_rooms = []
for room in rooms:
    standardized = room.title()
    standardized_rooms.append(standardized)

print(standardized_rooms)
# Output: ['Conference Room', 'Meeting Room', 'Break Room']

Removing Whitespace

Whitespace (spaces, tabs, newlines) at the beginning or end of strings can cause problems.

room_name = "  Conference Room  "

# Remove whitespace from both ends
clean_name = room_name.strip()
print(clean_name)  # Output: "Conference Room"

# Remove from left side only
clean_left = room_name.lstrip()
print(clean_left)  # Output: "Conference Room  "

# Remove from right side only
clean_right = room_name.rstrip()
print(clean_right)  # Output: "  Conference Room"

Why This Matters

# Data imported from Excel might have extra spaces
room_1 = "Conference Room"
room_2 = "Conference Room "  # Extra space at end

# These are NOT equal
print(room_1 == room_2)  # Output: False

# Clean the data first
room_1_clean = room_1.strip()
room_2_clean = room_2.strip()

print(room_1_clean == room_2_clean)  # Output: True

Finding Text in Strings

Check if a string contains certain text.

sheet_name = "A-101 Ground Floor Plan"

# Check if it contains "Floor"
if "Floor" in sheet_name:
    print("This is a floor plan")

# Check if it doesn't contain something
if "Ceiling" not in sheet_name:
    print("This is not a ceiling plan")

Find Position of Text

sheet_name = "A-101 Ground Floor Plan"

# Find where "Floor" starts
position = sheet_name.find("Floor")
print(position)  # Output: 14

# Find returns -1 if text is not found
position = sheet_name.find("Ceiling")
print(position)  # Output: -1

Replacing Text

Replace all occurrences of one string with another.

sheet_name = "A-101 Ground Floor Plan"

# Replace "Ground" with "First"
new_name = sheet_name.replace("Ground", "First")
print(new_name)  # Output: A-101 First Floor Plan

Architectural Use Case: Batch Renaming

# Update all sheet names from "Draft" to "Issued"
sheet_names = [
    "A-101 Draft Floor Plan",
    "A-102 Draft Floor Plan",
    "A-201 Draft Elevation"
]

issued_names = []
for sheet in sheet_names:
    new_name = sheet.replace("Draft", "Issued")
    issued_names.append(new_name)

print(issued_names)
# Output:
# ['A-101 Issued Floor Plan', 'A-102 Issued Floor Plan', 'A-201 Issued Elevation']

Splitting Strings

Break a string into a list of parts.

sheet_number = "A-101"

# Split at the hyphen
parts = sheet_number.split("-")
print(parts)  # Output: ['A', '101']

# Access individual parts
discipline = parts[0]
number = parts[1]

print("Discipline:", discipline)  # Output: Discipline: A
print("Number:", number)          # Output: Number: 101

Architectural Example: Parsing Sheet Numbers

sheet_numbers = ["A-101", "S-201", "M-301", "E-401"]

for sheet in sheet_numbers:
    parts = sheet.split("-")
    discipline = parts[0]
    number = parts[1]

    print(f"Sheet {sheet}: Discipline = {discipline}, Number = {number}")

# Output:
# Sheet A-101: Discipline = A, Number = 101
# Sheet S-201: Discipline = S, Number = 201
# Sheet M-301: Discipline = M, Number = 301
# Sheet E-401: Discipline = E, Number = 401

Joining Strings

Combine a list of strings into one string.

parts = ["A", "101"]

# Join with a hyphen
sheet_number = "-".join(parts)
print(sheet_number)  # Output: A-101

# Join with an underscore
file_name = "_".join(parts)
print(file_name)  # Output: A_101

Architectural Example: Building File Names

project_code = "2024-001"
discipline = "Architecture"
drawing_type = "Floor Plans"
revision = "R02"

# Join parts with underscores
parts = [project_code, discipline, drawing_type, revision]
file_name = "_".join(parts) + ".pdf"

print(file_name)
# Output: 2024-001_Architecture_Floor Plans_R02.pdf

String Formatting (f-strings)

A cleaner way to build strings with variables.

Instead of concatenating:

project = "Community Center"
year = 2024
message = "Project: " + project + ", Year: " + str(year)
print(message)

Use f-strings (formatted string literals):

project = "Community Center"
year = 2024
message = f"Project: {project}, Year: {year}"
print(message)

Both output: Project: Community Center, Year: 2024

Why f-strings Are Better

  • No need to convert numbers to strings
  • More readable
  • Easier to maintain

Architectural Examples

# Building report
floor_count = 12
floor_height = 3.2
total_height = floor_count * floor_height

report = f"Building has {floor_count} floors at {floor_height}m each = {total_height}m total"
print(report)
# Output: Building has 12 floors at 3.2m each = 38.4m total

# Sheet naming
discipline = "A"
number = 101
sheet_name = f"{discipline}-{number}"
print(sheet_name)
# Output: A-101

# Room naming
room_type = "Conference"
room_number = 201
full_name = f"{room_type} Room {room_number}"
print(full_name)
# Output: Conference Room 201

The Pain vs The Python Fix

The Pain: Renaming 200 sheets manually to follow a new naming standard.

The Python Fix: Define the pattern once, apply it to all sheets.

# Old naming: "A-101 - GROUND FLOOR PLAN"
# New naming: "A-101_Ground_Floor_Plan"

old_names = [
    "A-101 - GROUND FLOOR PLAN",
    "A-102 - FIRST FLOOR PLAN",
    "A-201 - NORTH ELEVATION"
]

new_names = []
for old_name in old_names:
    # Convert to title case
    name = old_name.title()
    # Replace " - " with "_"
    name = name.replace(" - ", "_")
    # Replace spaces with underscores
    name = name.replace(" ", "_")

    new_names.append(name)

for i, new_name in enumerate(new_names):
    print(f"{old_names[i]} → {new_name}")

# Output:
# A-101 - GROUND FLOOR PLAN → A-101_Ground_Floor_Plan
# A-102 - FIRST FLOOR PLAN → A-102_First_Floor_Plan
# A-201 - NORTH ELEVATION → A-201_North_Elevation

Common Mistakes

Mistake 1: Trying to change a string directly

Strings are immutable (cannot be changed after creation).

sheet_name = "A-101"
sheet_name[0] = "S"
# Error: TypeError: 'str' object does not support item assignment

Instead, create a new string:

sheet_name = "A-101"
new_name = "S" + sheet_name[1:]
print(new_name)  # Output: S-101

Mistake 2: Forgetting to convert numbers to strings

floor = 2
name = "Level " + floor
# Error: TypeError: can only concatenate str (not "int") to str

Fix:

floor = 2
name = "Level " + str(floor)
print(name)  # Output: Level 2

# Or use f-strings
name = f"Level {floor}"
print(name)  # Output: Level 2

Mistake 3: Off-by-one errors in slicing

sheet = "A-101"
number = sheet[2:4]  # Trying to get "101"
print(number)  # Output: 10 (not 101!)

# Correct
number = sheet[2:]
print(number)  # Output: 101

Mistake 4: Case-sensitive comparisons

room_1 = "Conference Room"
room_2 = "conference room"

print(room_1 == room_2)  # Output: False (different case)

# Fix: standardize case before comparing
print(room_1.lower() == room_2.lower())  # Output: True

Assignment

  1. Create a new file called string_practice.py
  2. Sheet naming exercise:
    • Create variables: discipline = "A", sheet_type = "Floor Plan", level = "02"
    • Combine them into: "A-Floor Plan-02"
    • Convert to: "A_FLOOR_PLAN_02" (uppercase, underscores)
  3. Room naming standardization:
    • Start with: rooms = ["conference room", "MEETING ROOM", "Break Room "]
    • Standardize to title case
    • Remove extra whitespace
    • Print the cleaned list
  4. Sheet number parsing:
    • Start with: sheet = "A-101-Ground-Floor-Plan"
    • Extract: discipline ("A")
    • Extract: number ("101")
    • Extract: description ("Ground-Floor-Plan")
    • Print each part separately
  5. File name builder:
    • Variables: project = "2024-001", drawing = "Floor Plans", revision = 3
    • Build: "2024-001_Floor_Plans_R03.pdf"
    • Use f-strings
  6. Batch renaming simulation:
    • Start with: ["A-101 Draft", "A-102 Draft", "A-201 Draft"]
    • Replace "Draft" with "Issued"
    • Print before and after
  7. Experiment:
    • Try to change a character in a string directly (see the error)
    • Slice your name to get just the first 3 letters
    • Check if "Floor" is in "Ground Floor Plan"

Knowledge Check

The following questions are an opportunity to reflect on key topics in this lesson.


Additional Resources

This section contains helpful links to related content. It isn't required, so consider it supplemental.

Updated on Mar 27, 2026