Table of Contents

# CSV Writer

The module will write object(s) to CSV file(s). The module supports two write modes:

- **Append & Roll**: Data from incoming messages are appended to the same file until the rotation time expires or the max lines rotation is reached. The file is then given a name that is a combination of `Base File Name` and a date/time string according to `Date Format`. After rotation new data is written to a new `.csv` file.
- **Single File**: All data is written to a single file that never rotates. Supports template syntax in the file name for dynamic file paths. If the file already exists, it will be overwritten.

## Settings

| Name | Requirements | Purpose | Default |
|------|-------------|---------|---------|
| Source Property | Length 1-64 | The property that contains the object(s) to write as CSV file | data |
| Target Property | Length 1-64 | The property to write the file rotation result into | data |
| Keep Properties | - | If true the Writer result will be added to the incoming data, otherwise the Writer result will be sent as a new message (only used in Single File mode) | true |
| Write Mode | - | Select between 'Append & Roll' (existing behavior) or 'Single File' (always write to the same file) | Append & Roll |
| Base File Name | Length 1-128 | The base name for the file (extension excluded).  | - |
| Date Format | Length 1-32 | The date format to use as a suffix to the `Target File Name` (only used in Append & Roll mode) | yyyyMMddHHmmssfff |
| Null Value | Max length 32 | Value to use for missing data | (empty) |
| Delimiter | Length 1-10 | The CSV delimiter to use | , |
| Add Header | - | If true the first line in the file will be a header line | true |
| Max Lines Rotation | - | Max lines written before rotation (only used in Append & Roll mode) | 1000 |
| Max Rotation Period | - | Max period to wait before rotation (only used in Append & Roll mode) | 10 minutes |
| Keep Properties | - | If true the Writer result will be added to the incoming data, otherwise the Writer result will be sent as a new message | true |

Note that at least one of the settings `Max Lines Rotation` or `Max Rotation Period` have to be set to a number > 0 when using **Append & Roll** mode.

## Input

The input message must have a `Source Property` containing the data to write to the CSV files.

### Supported Input Types

- **Single FlowMessage**: A single object with key/value pairs
- **Collection of FlowMessages**: An array of objects with key/value pairs

### Header Generation

When **Add Header** is enabled, the module will:

- For single objects: Use the object's property names as headers
- For arrays: Aggregate all unique property names across all objects to create a comprehensive header

### Missing Data Handling

When objects in an array have different properties, missing values are handled using the **Null Value** setting. For example, if one object has `{Id: 1, Name: "John"}` and another has `{Id: 2, Age: 25}`, the missing `Name` in the second object and missing `Age` in the first object will be filled with the specified null value.

## Output

### Append & Roll Mode

This module only sends data to the next module(s) in the flow when a file is rotated.

When the file is rotated, the next module(s) will be called with the information about the file written to `/path/filename.csv`. The object is written to the `Target Property` property. So if the `Target Property` = `data` the result could look like:

```json
{"data": "/somefolder/foo_20171120133455.csv"}

Single File Mode

In Single File mode, the module writes directly to the specified file and immediately sends the result to the next module(s) in the flow. If the file already exists, it will be overwritten.

Template Syntax

The Base File Name setting supports template syntax when using Single File mode. You can include placeholders that will be replaced with values from the incoming message:

  • {propertyName} - Replaced with the value of the specified property from the message
  • {year}, {month}, {day} - Can be used if these properties exist in the message
  • {messageId} - Useful for creating unique file names per message

Examples

  • data/output_{messageId}.csv - Creates files like data/output_12345.csv
  • reports/{year}/{month}/sales.csv - Creates files like reports/2025/08/sales.csv
  • {department}_{date}.csv - Creates files like marketing_2025-08-21.csv

Special Character Handling

The module properly handles special characters in CSV data:

  • Quotes: Values containing quotes are escaped according to CSV standards
  • Newlines: Multi-line values are properly quoted and preserved
  • Delimiters: Values containing the delimiter character are automatically quoted
  • Null Values: Missing or null values are replaced with the specified Null Value setting

Error Handling

The module will return errors in the following cases:

  • Missing Source Property in the incoming message
  • Invalid source data type (not a FlowMessage or collection of FlowMessages)
  • Empty FlowMessage objects (objects with no properties)
  • File system errors (permissions, disk space, etc.)
  • Invalid template syntax in file names

Examples

Example 1 - Single File Mode with KeepProperties

The sample shows how the KeepProperties setting affects the output message structure.

Settings

  • Write Mode = Single File
  • Base File Name = output/report
  • Source Property = data
  • Target Property = filename
  • Keep Properties = true
  • Add Header = true
  • Delimiter = ,

Incoming message

{
  "data": [
    {
      "productId": "P001",
      "sales": 150
    }
  ],
  "reportDate": "2025-08-27",
  "department": "sales"
}

Result with KeepProperties = true

Creates file: output/report.csv

productId,sales
"P001",150

Outgoing message:

{
  "data": [
    {
      "productId": "P001",
      "sales": 150
    }
  ],
  "reportDate": "2025-08-27",
  "department": "sales",
  "filename": "output/report"
}

Result with KeepProperties = false

Same CSV file is created, but outgoing message only contains the result:

{
  "filename": "output/report"
}

Example 2 - Single File Mode with Template

The sample shows how to use template syntax to create dynamic file names.

Settings

  • Write Mode = Single File
  • Base File Name = reports/{department}_{date}
  • Source Property = data
  • Add Header = true
  • Delimiter = ,

Incoming message

{
  "data": [
    {
      "employeeId": 1001,
      "name": "John Doe",
      "salary": 50000
    },
    {
      "employeeId": 1002,
      "name": "Jane Smith",
      "salary": 55000
    }
  ],
  "department": "sales",
  "date": "2025-08-21"
}

Result

Creates file: reports/sales_2025-08-21.csv

employeeId,name,salary
1001,"John Doe",50000
1002,"Jane Smith",55000

Example 3 - Append & Roll Mode with Rotation

The sample shows file rotation based on line count.

Settings

  • Write Mode = Append & Roll
  • Base File Name = data/temperature
  • Max Lines Rotation = 2
  • Max Rotation Period = 0
  • Source Property = readings
  • Add Header = true
  • Date Format = yyyyMMddHHmmss

Incoming messages

// Message 1
{
  "readings": [
    {
      "sensorId": "S001",
      "temperature": 23.5,
      "humidity": 65
    },
    {
      "sensorId": "S002",
      "temperature": 24.1,
      "humidity": 62
    }
  ]
}

// Message 2
{
  "readings": [
    {
      "sensorId": "S003",
      "temperature": 22.8,
      "humidity": 68
    }
  ]
}

Result

After processing Message 1, creates file: data/temperature_20250821143022.csv

sensorId,temperature,humidity
"S001",23.5,65
"S002",24.1,62

After processing Message 2 (triggers rotation), the first file is closed and a new file is created: data/temperature_20250821143025.csv

sensorId,temperature,humidity
"S003",22.8,68

Outgoing rotation message

{
  "data": "data/temperature_20250821143022.csv"
}

Example 4 - Missing Data Handling

The sample shows how missing properties are handled with null values.

Settings

  • Write Mode = Single File
  • Base File Name = mixed_data
  • Source Property = data
  • Add Header = true
  • Null Value = N/A

Incoming message

{
  "data": [
    {
      "id": 1,
      "name": "Product A",
      "price": 29.99
    },
    {
      "id": 2,
      "name": "Product B",
      "category": "Electronics"
    },
    {
      "id": 3,
      "price": 15.50,
      "category": "Books"
    }
  ]
}

Result

Creates file: mixed_data.csv

id,name,price,category
1,"Product A",29.99,"N/A"
2,"Product B","N/A","Electronics"
3,"N/A",15.50,"Books"