How to Export a NetSuite Saved Search to CSV with N/task

Submit a SearchTask, check completion before reading its file and verify the resulting CSV bytes in an illustrated local lifecycle walkthrough.

The quick answer

Create task.TaskType.SEARCH, set the saved search ID and one CSV destination, then submit. Keep the returned task ID. In a later execution, check the task status and read the file only after COMPLETE. The submitted task ID does not mean the export is ready.

This walkthrough executes local producer and consumer modules with N/task and N/file mocked. Manual task advancement is test control. It writes and downloads a real local CSV, but it does not run a NetSuite scheduler, access an account or establish native CSV formatting.

Before you start

The fixture exports saved search 620 into an existing CSV target, file 910, named customer_export.csv. Its File Cabinet folder is Exports, ID 70. The returned search-export-001 identifies the asynchronous task. These are three different identifiers: search, file and task. The folder ID is not the file target.

The local search has two data rows and three columns. One customer name contains a comma and quotes: Harbor, "West". Its Note contains an embedded newline. A standard-library writer produces 110 UTF-8 bytes, and a CSV parser checks that the original values survive. Those counts belong to this fixture; they are not general SearchTask guarantees.

In an account, verify access to the saved search, its underlying records and the destination file. Search criteria and execution context affect the exported rows. This guide does not deploy a monitor, durable task store, retry process or completion dependency.

01. Identify the existing destination

Search the local File Cabinet for customer_export.csv. It already exists as file 910 and starts at 0 B. The crop focuses on its filename and size; enlarge it to verify the internal ID and Exports folder.

Existing local customer_export.csv starts at 0 B. Enlarge to verify destination file 910.

Use fileId for an existing CSV file, or filePath for the target path. Supply exactly one. Oracle documents an error when both are set. Do not substitute a folder ID. Also verify target state and permissions; submission alone does not establish atomic replacement or protection from concurrent writers. Oracle: SearchTask target properties

02. Submit the search task

The scheduled-script producer creates and submits a SearchTask. It logs the returned ID and exits. It contains no manual CSV row loop and does not wait for the export.

const exportTask = task.create({
  taskType: task.TaskType.SEARCH
});
exportTask.savedSearchId = 620;
exportTask.fileId = 910;
const taskId = exportTask.submit();
log.audit({
  title: 'Submitted search export',
  details: taskId
});

The actual local module returns search-export-001 with PENDING status. The destination is still 0 B. A submitted task ID is an acknowledgment of the job, not completed file content.

Submitted task search-export-001 is PENDING; its local destination remains 0 B.

Retain the task ID for the later consumer. Logging it here makes the teaching example visible; production orchestration needs durable tracking or a configured completion mechanism. SearchTask.submit uses 100 governance units. Oracle documents a concurrency limit aligned with CSV import and File Cabinet size limits; no fixed completion time is promised. Oracle: SearchTask.submit

03. Keep the consumer behind completion

Run the separate consumer while the local task is PENDING. It returns ready:false and N/file read count 0. Advance the local test task to PROCESSING, then check again. It still performs no file load.

PROCESSING returns ready:false and N/file read count 0.

This is the consumer's gate. FAILED is handled separately, and every non-COMPLETE state returns before N/file is called.

const state = task.checkStatus({
  taskId
});
if (state.status ===
    task.TaskStatus.FAILED) {
  return {
    ready: false,
    failed: true
  };
}
if (state.status !==
    task.TaskStatus.COMPLETE) {
  return {
    ready: false,
    status: state.status
  };
}
const csvFile = file.load({
  id: state.fileId
});
const contents = csvFile.getContents();

Use later checks or a suitable configured dependent script. Do not put a busy loop or sleep in the producer. task.checkStatus has no governance charge, but repeated checks inside one execution do not make an asynchronous export synchronous. The local harness's advance command is not a NetSuite API. Oracle: task.checkStatus

04. Verify the actual CSV bytes

Advance the local task to COMPLETE, then call the consumer separately. It uses the fileId from the completed status, loads 110 bytes, and parses two data rows and three columns. The recorded SHA-256 is displayed over two lines for readability.

The parsed customer retains its comma and quotes. The parsed Note retains the newline, displayed as an escaped newline in the value preview. The full screenshot also shows the raw CSV with its quoted multiline field.

Completed local file 910 has 110 B and preserves parsed values. Full image includes raw CSV.

This is a byte-level check of the local artifact. The producer delegates export to SearchTask in the platform API; the local harness uses its own standard-library serializer and makes no claim of byte-identical NetSuite output. A completed search can also validly return only column headers when no data rows match.

This tiny consumer uses getContents, which has a 10 MB memory limit. Larger exports require an appropriate reading and parsing strategy. Physical line count is not CSV row count: quoted fields can contain newlines, so splitting on newline is not a valid CSV parser. Oracle: File.getContents

05. Reconcile the File Cabinet download

Return to the local File Cabinet and find the same filename and internal ID 910. Its size is now 110 B. Download the file; the capture driver compares the downloaded bytes with the actual completed local CSV and records a matching SHA-256.

The same local customer_export.csv now contains 110 B; download bytes match the actual local file.

The same local identity, size and download contents agree. No account file was created, replaced or downloaded.

Common questions

Does submit mean the CSV is ready?

It returns the asynchronous task ID. Check the status later and consume the file only after COMPLETE. The file may exist beforehand with stale or empty content.

Is fileId the folder ID?

It identifies the destination file. This fixture uses file 910 inside folder 70. filePath is the alternative target property; do not set both.

Why use N/task instead of manually constructing CSV with N/file?

SearchTask runs the saved-search export asynchronously and writes to its configured CSV target. N/file creates or reads files directly. The producer does not need to concatenate every search result and escape CSV fields itself.

Should I repeatedly check status in a while loop?

Exit and check in a later execution, or configure a suitable dependency. This example provides a separate consumer helper, not deployed monitoring or retry infrastructure.

Does the local advance command model NetSuite timing?

It provides deterministic test control for the local mocks. It does not establish queue delay, concurrency, role permissions, overwrite behavior or production file generation.

Can a completed export have no data rows?

A search that matches no records can produce a header-only CSV. Distinguish successful completion from the business expectation for row count. Two data rows are specific to this example.

Can I count CSV rows by counting newline characters?

Use a CSV parser. This file has an embedded newline inside one quoted Note, so a physical-line count would overstate its data rows. Preserve commas, escaped quotes and multiline values.

Can getContents read any exported file size?

Its in-memory content limit is 10 MB. That limit is separate from search-task and File Cabinet limits. Choose a reading/parser strategy appropriate to large files while preserving quoted-field boundaries.

Supporting sources