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

# Working with File Formats

> Recipes for reading and writing CSV, XML, XLSX, PDF, DOCX, and PPTX files with the Opus SDK.

These recipes build on the core file API described in [Overview](/opus-sdk/overview) and use the libraries listed in [Available Packages](/opus-sdk/available-packages). Each example runs in an [Opus Code](/tasks/agent/opus-code) task, where `Opus.file.create`, `Opus.file.download`, and `Opus.file.upload` give you everything you need to read, transform, and produce files.

## CSV Files

**Create a simple CSV from scratch:**

```python theme={null}
import csv

output = Opus.file.create("results", "CSV")

with output.open("w") as f:
    writer = csv.writer(f)
    writer.writerow(["name", "score"])
    writer.writerow(["Alice", 95])
    writer.writerow(["Bob", 87])

file_url = Opus.file.upload(output)
```

**Build a CSV with DictWriter:**

```python theme={null}
import csv

output = Opus.file.create("inventory", "CSV")

with output.open("w") as f:
    writer = csv.DictWriter(f, fieldnames=["product", "quantity", "price"])
    writer.writeheader()
    writer.writerow({"product": "Widget", "quantity": 100, "price": 25.00})
    writer.writerow({"product": "Gadget", "quantity": 50, "price": 49.99})

file_url = Opus.file.upload(output)
```

**Read and filter a downloaded CSV:**

```python theme={null}
import csv

file = Opus.file.download("https://files.opus.com/data/employees.csv")

with file.open("r") as f:
    reader = csv.DictReader(f)
    for row in reader:
        if int(row["score"]) > 30:
            print(row["name"], row["score"])
```

**Download a CSV, filter rows, and upload as a new file:**

```python theme={null}
import csv

source = Opus.file.download("https://files.opus.com/data/scores.csv")
output = Opus.file.create("high_scores", "CSV")

with source.open("r") as src, output.open("w") as dst:
    reader = csv.DictReader(src)
    writer = csv.DictWriter(dst, fieldnames=reader.fieldnames)
    writer.writeheader()
    for row in reader:
        if float(row["score"]) > 90:
            writer.writerow(row)

file_url = Opus.file.upload(output)
```

## XML Files

**Create an XML file from scratch:**

```python theme={null}
import xml.etree.ElementTree as ET

root = ET.Element("catalog")

for title, price in [("Widget", "25.00"), ("Gadget", "49.99")]:
    item = ET.SubElement(root, "item")
    ET.SubElement(item, "title").text = title
    ET.SubElement(item, "price").text = price

output = Opus.file.create("catalog", "XML")

tree = ET.ElementTree(root)
ET.indent(tree)
with output.open("wb") as f:
    tree.write(f, encoding="utf-8", xml_declaration=True)

file_url = Opus.file.upload(output)
```

**Parse a downloaded XML file:**

```python theme={null}
import xml.etree.ElementTree as ET

file = Opus.file.download("https://files.opus.com/data/catalog.xml")

tree = ET.parse(file.open("r"))
root = tree.getroot()

for item in root.findall("item"):
    title = item.find("title").text
    price = item.find("price").text
    print(f"{title}: ${price}")
```

**Download an XML, modify it, and re-upload:**

```python theme={null}
import xml.etree.ElementTree as ET

file = Opus.file.download("https://files.opus.com/data/config.xml")

tree = ET.parse(file.open("r"))
root = tree.getroot()

# Update a setting
setting = root.find(".//setting[@name='timeout']")
if setting is not None:
    setting.set("value", "60")

ET.indent(tree)
with file.open("wb") as f:
    tree.write(f, encoding="utf-8", xml_declaration=True)

new_url = Opus.file.upload(file)
```

## XLS & XLSX Files

Use `openpyxl` to read and write XLSX spreadsheets.

**Create an XLSX from scratch:**

```python theme={null}
from openpyxl import Workbook

wb = Workbook()
ws = wb.active
ws.title = "Sales"

ws.append(["product", "quantity", "price"])
ws.append(["Widget", 100, 25.00])
ws.append(["Gadget", 50, 49.99])

output = Opus.file.create("sales_report", "XLSX")
with output.open("wb") as f:
    wb.save(f)

file_url = Opus.file.upload(output)
```

**Read and filter a downloaded XLSX:**

```python theme={null}
from openpyxl import load_workbook

file = Opus.file.download("https://files.opus.com/data/report.xlsx")

wb = load_workbook(file.open("rb"))
ws = wb.active

headers = [cell.value for cell in ws[1]]
for row in ws.iter_rows(min_row=2, values_only=True):
    data = dict(zip(headers, row))
    if data["quantity"] > 50:
        print(data["product"], data["quantity"])
```

**Download an XLSX, modify it, and re-upload:**

```python theme={null}
from openpyxl import load_workbook

file = Opus.file.download("https://files.opus.com/data/report.xlsx")

wb = load_workbook(file.open("rb"))
ws = wb.active

# Add a total row
total = sum(row[2] for row in ws.iter_rows(min_row=2, values_only=True))
ws.append(["Total", "", total])

with file.open("wb") as f:
    wb.save(f)

new_url = Opus.file.upload(file)
```

**Convert a downloaded XLSX to CSV:**

```python theme={null}
import csv
from openpyxl import load_workbook

file = Opus.file.download("https://files.opus.com/data/report.xlsx")

wb = load_workbook(file.open("rb"))
ws = wb.active

output = Opus.file.create("report", "CSV")
with output.open("w") as f:
    writer = csv.writer(f)
    for row in ws.iter_rows(values_only=True):
        writer.writerow(row)

file_url = Opus.file.upload(output)
```

## PDF Files

Three PDF libraries are available: `fitz` (PyMuPDF), `fpdf2`, and `PyPDF2`.

### PyMuPDF (`fitz`)

**Create a PDF from scratch:**

```python theme={null}
import fitz

doc = fitz.open()
page = doc.new_page()

page.insert_text(fitz.Point(72, 72), "Hello, world!", fontsize=16)
page.insert_text(fitz.Point(72, 100), "Generated with PyMuPDF.", fontsize=12)

output = Opus.file.create("greeting", "PDF")
doc.save(output.open("wb"))
doc.close()

file_url = Opus.file.upload(output)
```

**Extract text from a downloaded PDF:**

```python theme={null}
import fitz

file = Opus.file.download("https://files.opus.com/data/document.pdf")

doc = fitz.open(file.open("rb"))
for page in doc:
    print(page.get_text())
doc.close()
```

**Extract text from a specific page range:**

```python theme={null}
import fitz

file = Opus.file.download("https://files.opus.com/data/document.pdf")

doc = fitz.open(file.open("rb"))
for page in doc[2:5]:  # pages 3 through 5 (0-indexed)
    print(f"--- Page {page.number + 1} ---")
    print(page.get_text())
doc.close()
```

**Download a PDF, add a watermark, and re-upload:**

```python theme={null}
import fitz

file = Opus.file.download("https://files.opus.com/data/report.pdf")

doc = fitz.open(file.open("rb"))
for page in doc:
    page.insert_text(
        fitz.Point(200, 400),
        "CONFIDENTIAL",
        fontsize=48,
        color=(0.8, 0, 0),
        rotate=270,
    )

doc.save(file.open("wb"))
doc.close()

new_url = Opus.file.upload(file)
```

**Extract images from a PDF and upload each as PNG:**

```python theme={null}
import fitz

file = Opus.file.download("https://files.opus.com/data/report.pdf")

png_file_urls = []
doc = fitz.open(file.open("rb"))
for page_num, page in enumerate(doc):
    for img_index, img in enumerate(page.get_images()):
        xref = img[0]
        pix = fitz.Pixmap(doc, xref)

        output = Opus.file.create(f"page{page_num + 1}_img{img_index + 1}", "PNG")
        output.write_bytes(pix.tobytes("png"))
        file_url = Opus.file.upload(output)
        png_file_urls.append(file_url)

        pix = None
doc.close()
```

**Convert each page of a PDF to a PNG image:**

```python theme={null}
import fitz

file = Opus.file.download("https://files.opus.com/data/document.pdf")

png_file_urls = []
doc = fitz.open(file.open("rb"))
for page in doc:
    pix = page.get_pixmap(dpi=150)

    output = Opus.file.create(f"page_{page.number + 1}", "PNG")
    output.write_bytes(pix.tobytes("png"))
    file_url = Opus.file.upload(output)
    png_file_urls.append(file_url)

    pix = None
doc.close()
```

### PyPDF2

**Merge multiple downloaded PDFs into one:**

```python theme={null}
from PyPDF2 import PdfMerger

urls = [
    "https://files.opus.com/data/part1.pdf",
    "https://files.opus.com/data/part2.pdf",
    "https://files.opus.com/data/part3.pdf",
]

merger = PdfMerger()
for url in urls:
    file = Opus.file.download(url)
    merger.append(file.open("rb"))

output = Opus.file.create("merged", "PDF")
merger.write(output.open("wb"))
merger.close()

file_url = Opus.file.upload(output)
```

**Extract specific pages from a PDF:**

```python theme={null}
from PyPDF2 import PdfReader, PdfWriter

file = Opus.file.download("https://files.opus.com/data/document.pdf")

reader = PdfReader(file.open("rb"))
writer = PdfWriter()

for page_num in [0, 2, 4]:  # pages 1, 3, 5 (0-indexed)
    writer.add_page(reader.pages[page_num])

output = Opus.file.create("selected_pages", "PDF")
writer.write(output.open("wb"))

file_url = Opus.file.upload(output)
```

**Rotate pages in a PDF:**

```python theme={null}
from PyPDF2 import PdfReader, PdfWriter

file = Opus.file.download("https://files.opus.com/data/document.pdf")

reader = PdfReader(file.open("rb"))
writer = PdfWriter()

for page in reader.pages:
    page.rotate(90)
    writer.add_page(page)

with file.open("wb") as f:
    writer.write(f)

new_url = Opus.file.upload(file)
```

## DOCX Files

Use `python-docx` to read and write Word documents.

**Create a DOCX from scratch:**

```python theme={null}
from docx import Document

doc = Document()
doc.add_heading("Monthly Report", level=1)
doc.add_paragraph("This report covers Q1 performance.")

table = doc.add_table(rows=1, cols=3)
table.style = "Table Grid"
table.rows[0].cells[0].text = "Product"
table.rows[0].cells[1].text = "Quantity"
table.rows[0].cells[2].text = "Price"

for product, qty, price in [("Widget", "100", "$25.00"), ("Gadget", "50", "$49.99")]:
    row = table.add_row()
    row.cells[0].text = product
    row.cells[1].text = qty
    row.cells[2].text = price

output = Opus.file.create("monthly_report", "DOCX")
doc.save(output.open("wb"))

file_url = Opus.file.upload(output)
```

**Read text from a downloaded DOCX:**

```python theme={null}
from docx import Document

file = Opus.file.download("https://files.opus.com/data/report.docx")

doc = Document(file.open("rb"))
for para in doc.paragraphs:
    print(para.text)
```

**Read tables from a downloaded DOCX:**

```python theme={null}
from docx import Document

file = Opus.file.download("https://files.opus.com/data/report.docx")

doc = Document(file.open("rb"))
for table in doc.tables:
    for row in table.rows:
        print([cell.text for cell in row.cells])
```

**Download a DOCX, modify it, and re-upload:**

```python theme={null}
from docx import Document

file = Opus.file.download("https://files.opus.com/data/report.docx")

doc = Document(file.open("rb"))
doc.add_heading("Appendix", level=2)
doc.add_paragraph("Additional notes added programmatically.")

doc.save(file.open("wb"))

new_url = Opus.file.upload(file)
```

## PPTX Files

Use `python-pptx` to read and modify PowerPoint presentations.

<Warning>
  PPTX is not a supported file type for `Opus.file.create`. You can download existing PPTX files, modify them, and re-upload.
</Warning>

**Read text from all slides of a downloaded PPTX:**

```python theme={null}
from pptx import Presentation

file = Opus.file.download("https://files.opus.com/data/presentation.pptx")

prs = Presentation(file.open("rb"))
for slide_num, slide in enumerate(prs.slides, 1):
    print(f"--- Slide {slide_num} ---")
    for shape in slide.shapes:
        if shape.has_text_frame:
            print(shape.text)
```

**Download a PPTX, add a slide, and re-upload:**

```python theme={null}
from pptx import Presentation
from pptx.util import Inches, Pt

file = Opus.file.download("https://files.opus.com/data/presentation.pptx")

prs = Presentation(file.open("rb"))

slide_layout = prs.slide_layouts[1]  # title + content layout
slide = prs.slides.add_slide(slide_layout)

slide.shapes.title.text = "Summary"
slide.placeholders[1].text = "Automatically generated slide."

prs.save(file.open("wb"))

new_url = Opus.file.upload(file)
```

**Download a PPTX and replace text across all slides:**

```python theme={null}
from pptx import Presentation

file = Opus.file.download("https://files.opus.com/data/template.pptx")

prs = Presentation(file.open("rb"))
for slide in prs.slides:
    for shape in slide.shapes:
        if shape.has_text_frame:
            for paragraph in shape.text_frame.paragraphs:
                for run in paragraph.runs:
                    run.text = run.text.replace("{{COMPANY}}", "Acme Corp")

prs.save(file.open("wb"))

new_url = Opus.file.upload(file)
```

## Related

<CardGroup cols={2}>
  <Card title="Overview" icon="cube" href="/opus-sdk/overview">
    Learn the core file API: create, download, and upload.
  </Card>

  <Card title="Available Packages" icon="box-open" href="/opus-sdk/available-packages">
    See every Python library you can import in Opus Code.
  </Card>

  <Card title="Opus Code" icon="code" href="/tasks/agent/opus-code">
    Run these recipes in a Python task inside your workflow.
  </Card>
</CardGroup>
