> ## Documentation Index
> Fetch the complete documentation index at: https://docs.getgranite.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Creating RPA Scripts

> Write your first RPA automation script

## Script Basics

RPA scripts in Granite use the Robocorp framework with Python.

## Minimal Example

```python theme={null}
from robocorp.tasks import task

@task
def my_automation():
    """My first automation."""
    print("Hello from Granite!")
```

The `@task` decorator marks the entry point.

## Browser Automation

```python theme={null}
from robocorp.tasks import task
from robocorp import browser

@task
def web_automation():
    # Navigate
    browser.goto("https://example.com")

    # Fill form
    browser.fill("input#email", "user@example.com")
    browser.fill("input#password", "secret")

    # Click
    browser.click("button#login")

    # Wait for result
    browser.wait_for_text("Welcome")

    # Extract data
    name = browser.text("span.username")
    print(f"Logged in as: {name}")
```

## Desktop Automation

```python theme={null}
from robocorp.tasks import task
from RPA.Desktop import Desktop

desktop = Desktop()

@task
def desktop_automation():
    # Open application
    desktop.open_application("notepad.exe")

    # Type text
    desktop.type_text("Hello from Granite!")

    # Keyboard shortcuts
    desktop.press_keys("ctrl", "s")

    # Click at coordinates
    desktop.click_at(100, 200)
```

## Excel Automation

```python theme={null}
from robocorp.tasks import task
from RPA.Excel.Files import Files

@task
def excel_automation():
    excel = Files()

    # Open workbook
    excel.open_workbook("data.xlsx")

    # Read data
    data = excel.read_worksheet_as_table("Sheet1")

    # Process rows
    for row in data:
        print(row["Name"], row["Amount"])

    # Write data
    excel.set_cell_value(1, 1, "Updated!")

    # Save
    excel.save_workbook()
```

## Error Handling

```python theme={null}
from robocorp.tasks import task
from robocorp import browser

@task
def safe_automation():
    try:
        browser.goto("https://example.com")
        browser.click("button#submit")
    except Exception as e:
        print(f"Error: {e}")
        # Take screenshot for debugging
        browser.screenshot("error.png")
        raise
```

## Waiting for Elements

```python theme={null}
from robocorp import browser

# Wait for element to appear
browser.wait_for_element("div.success", timeout=10)

# Wait for text
browser.wait_for_text("Complete", timeout=30)

# Custom wait
import time
time.sleep(2)  # Wait 2 seconds
```

## Best Practices

<AccordionGroup>
  <Accordion title="Use explicit waits">
    Don't use `time.sleep()` everywhere. Use `wait_for_element` or `wait_for_text` for reliability.
  </Accordion>

  <Accordion title="Handle errors gracefully">
    Wrap risky operations in try/except. Take screenshots on failure.
  </Accordion>

  <Accordion title="Use meaningful names">
    Name functions and variables clearly. Future you will thank you.
  </Accordion>

  <Accordion title="Test incrementally">
    Build and test one step at a time. Don't write the whole script first.
  </Accordion>
</AccordionGroup>

## Script Structure

Recommended file organization:

```
my_automation/
├── tasks.py         # Main script
├── config.py        # Configuration
├── helpers.py       # Utility functions
└── robot.yaml       # Robocorp config
```

## Next Steps

<CardGroup cols={2}>
  <Card title="RPA Overview" icon="robot" href="/rpa-automation/overview">
    Learn more about RPA
  </Card>

  <Card title="Run Logs" icon="list" href="/dashboard/run-logs">
    View execution history
  </Card>
</CardGroup>
