Skip to main content

Overview

The ctx object provides low-level methods for directly accessing and manipulating cells and rows by their IDs or by querying for specific values. These methods are useful when you need precise control over individual cells or when working with dynamic references.

Row Methods

ctx.row()

Get a row’s UUID by using a row selector.
ctx.row({ sel: RowSelector }): string
Row Selector: A row can be selected by:
  • id - The UUID of the row
  • index - The numeric index of the row (0-based)
  • label - A label assigned to the row
Example:
// Get row by index
const rowId = ctx.row({ sel: { index: 0 } });

// Get row by ID
const rowId = ctx.row({ sel: { id: "123e4567-e89b-12d3-a456-426614174000" } });

// Get row by label
const rowId = ctx.row({ sel: { label: "header_row" } });

ctx.getRowByValue()

Find a single row where a column matches a specific value.
ctx.getRowByValue(columnName: string, value: any): Promise<Row | null>
Parameters:
  • columnName - The name of the column to search
  • value - The value to match
Returns: A Row object if found, or null if no match Example:
// Find a company by name
const company = await ctx.getRowByValue("name", "Acme Corp");

if (company) {
   console.log(`Found company at index ${company.index}`);
   console.log(`Website: ${company.get("website")}`);
} else {
   console.log("Company not found");
}

ctx.setRowValues()

Set multiple values on a specific row by its ID.
ctx.setRowValues(rowId: string, values: Record<string, any>): void
Parameters:
  • rowId - The UUID of the row to update
  • values - An object mapping column names to new values
Example:
const companyRow = await ctx.getRowByValue("name", "Acme Corp");

if (companyRow) {
   ctx.setRowValues(companyRow.id, {
      status: "verified",
      last_updated: new Date().toISOString(),
      employee_count: 500,
   });
}

Column Methods

ctx.col()

Get a column’s UUID by its name.
ctx.col(columnName: string): string
Parameters:
  • columnName - The name of the column
Returns: The UUID of the column Example:
const emailColId = ctx.col("email");
const statusColId = ctx.col("status");

console.log(`Email column ID: ${emailColId}`);

Cell Methods

ctx.setCell()

Set the value of a specific cell by row and column IDs.
ctx.setCell({ rowId: string, colId: string, value: any }): void
Parameters:
  • rowId - The UUID of the row
  • colId - The UUID of the column
  • value - The new value to set
Example:
const rowId = ctx.row({ sel: { index: 5 } });
const colId = ctx.col("status");

ctx.setCell({
   rowId,
   colId,
   value: "completed",
});

ctx.setCellMetadata()

Set metadata on a specific cell.
ctx.setCellMetadata({
   rowId: string,
   colId: string,
   metadata: Record<string, any>
}): void
Parameters:
  • rowId - The UUID of the row
  • colId - The UUID of the column
  • metadata - An object containing metadata key-value pairs
Example:
const rowId = ctx.row({ sel: { index: 0 } });
const colId = ctx.col("ai_analysis");

ctx.setCellMetadata({
   rowId,
   colId,
   metadata: {
      model: "gpt-5-mini",
      cost: 0.002,
      executionTime: 1234,
      timestamp: new Date().toISOString(),
   },
});

Context Properties

ctx.rowId

The UUID of the currently executing row.
const currentRowId = ctx.rowId;

ctx.colId

The UUID of the currently executing column.
const currentColId = ctx.colId;
Example:
// Store metadata on the current cell
ctx.setCellMetadata({
   rowId: ctx.rowId,
   colId: ctx.colId,
   metadata: {
      lastRun: new Date().toISOString(),
   },
});

Common Patterns

Dynamic Cell Updates

// Update a specific cell based on dynamic logic
const targetRowIndex = 10;
const targetColumn = "score";

const rowId = ctx.row({ sel: { index: targetRowIndex } });
const colId = ctx.col(targetColumn);

ctx.setCell({
   rowId,
   colId,
   value: 95,
});

Batch Cell Operations

// Update multiple cells in a specific column
const statusColId = ctx.col("status");

for (let i = 0; i < 10; i++) {
   const rowId = ctx.row({ sel: { index: i } });

   ctx.setCell({
      rowId,
      colId: statusColId,
      value: "processed",
   });
}

Cross-Reference Lookups

// Find a related record and copy data
const relatedCompany = await ctx.getRowByValue("name", ctx.thisRow.get("company_name"));

if (relatedCompany) {
   ctx.thisRow.set({
      company_id: relatedCompany.id,
      company_website: relatedCompany.get("website"),
      company_industry: relatedCompany.get("industry"),
   });
} else {
   console.log("Related company not found");
}

Metadata Tracking

// Track execution metadata for the current cell
ctx.setCellMetadata({
   rowId: ctx.rowId,
   colId: ctx.colId,
   metadata: {
      executedAt: new Date().toISOString(),
      executionCount: (existingMetadata?.executionCount || 0) + 1,
      lastError: null,
   },
});

Conditional Row Updates

// Find and update rows based on criteria
const pendingCompanies = await ctx.sheet("Companies").getRowsByValue("status", "pending");

for (const company of pendingCompanies) {
   const website = company.get("website");

   if (website) {
      // Update using row ID
      ctx.setRowValues(company.id, {
         status: "processing",
         started_at: new Date().toISOString(),
      });

      // Perform enrichment...
   }
}

When to Use These Methods

Use high-level methods when possible:
  • Use ctx.thisRow.get() and ctx.thisRow.set() for current row operations
  • Use ctx.sheet().addRow() for creating rows in other sheets
  • Use ctx.thisRow.getRelatedRows() for foreign key relationships
Use low-level methods when you need:
  • Direct cell access by ID
  • Dynamic row/column references
  • Batch operations across multiple rows
  • Metadata management on specific cells