# MapTo

Let's take a look at the <mark style="color:purple;">**`.MapTo`**</mark> method (the primary transform method) and understand all of the available options. You can customize this transformation down to every single column or cell that gets read.

MapTo works by starting from a DataTable, sending the data through a map, and producing reports and target results. Every option here assists in that process and allows you to customize exactly what happens at every single cell.&#x20;

## Example 1 - Just a map

It is possible to execute a transform by only having a map and source data. If this is the use case you need, it's only one line of code

```csharp
var result = new DataTable().MapTo(
    Transformer.GetMapFromFile("map.xlsx", out var mreport).FirstOrDefault());
```

## Example 2 - Maps and a lookup

If your map contains lookups and you need to reference them include them in the list of paramaters.

```csharp
var result = new DataTable().MapTo(
    Transformer.GetMapFromFile("map.xlsx", out var mreport).FirstOrDefault(),
    
    Transformer.ToGroupHash(Transformer.GetLookupFromFile("lookups.csv", out var lreport)));
```

{% hint style="info" %}
The <mark style="color:orange;">`ToGroupHash`</mark> function takes cares of producing a valid hashed lookup table for the transformer to work on. Before this step, it's very easy to read and modify the raw <mark style="color:orange;">`LookupMap`</mark> objects.&#x20;
{% endhint %}

## Example 3 - Adding conversion functions

Transforms allows you to specify many different ways of customizing the conversion process. Here's two of them that are "in place" and don't involve writing [Transform Processes](https://docs.perigee.software/transform-sdk/authoring-plugins/transform-process).&#x20;

This will convert `colID` 1 from the mapping specification to an uppercase string whenever possible.&#x20;

```csharp
//Define custom transforms: 
//  - Transform colID 1 ToUpper
var customConversions = new Dictionary<int, Func<object, object, DataRow, MappingColumn, long, object>> {
        { 1, (value, defaultValue, row, map, index) => value?.ToString()?.ToUpper() ?? defaultValue }
    };
    
var result = new DataTable().MapTo(
    Transformer.GetMapFromFile("map.xlsx", out var mreport).FirstOrDefault(),
    Transformer.ToGroupHash(Transformer.GetLookupFromFile("lookups.csv", out var lreport)), 
    
    CustomConversions: customConversions);
```

{% hint style="success" %}
**Custom Conversion functions** allow you to modify the incoming data however you like. Internally these functions are used to convert the data when no registered converter is assigned for the given `colID` of the map. \
\
Values passed into the function are:&#x20;

* <mark style="color:orange;">`value`</mark> of object
* <mark style="color:orange;">`default value`</mark> of column (if exists)
* <mark style="color:orange;">`DataRow`</mark> of the object being loaded
* <mark style="color:orange;">`MappingSpecification`</mark> of the current running process.
* <mark style="color:orange;">`long`</mark> row index of the row
  {% endhint %}

## Example 4 - OnBeforeTableAdded&#x20;

Maybe you need to statically set a value, or calculate something before it proceeds to the [plugin processes](https://docs.perigee.software/transform-sdk/authoring-plugins).  You may modify the <mark style="color:orange;">`DataRow`</mark> one last time before it is added to the resulting table.&#x20;

```csharp
//Define custom transforms: 
//  - Transform colID 1 ToUpper
var customConversions = new Dictionary<int, Func<object, object, DataRow, MappingColumn, long, object>> {
        { 1, (value, defaultValue, row, map, index) => value?.ToString()?.ToUpper() ?? defaultValue }
    };
    
var result = new DataTable().MapTo(
    Transformer.GetMapFromFile("map.xlsx", out var mreport).FirstOrDefault(),
    Transformer.ToGroupHash(Transformer.GetLookupFromFile("lookups.csv", out var lreport)), 
    CustomConversions: customConversions,
    
    OnBeforeTableAdd: row => { row["Status"] = "New"; });
```

## Example 5 - Plugins

One of the most important and powerful features of the transform engine is the ability to run plugins. Both [DataQuality](https://docs.perigee.software/transform-sdk/authoring-plugins/data-quality) and [Transform](https://docs.perigee.software/transform-sdk/authoring-plugins/transform-process) plugins are baked right into the transform process and you can specify which plugins, as well as which partitions of those plugins to run.&#x20;

The **`AutoAddMapToPartitionKeys`** option tells the transformer to automatically assign the [DataTable (Transform Group)](https://docs.perigee.software/transforms/the-mapping-document#transformgroup) name to the list of assigned partitions. This is useful when the partition key contains specific map transform groups.&#x20;

{% hint style="success" %} <mark style="color:red;">**Partition Keys**</mark> - This specifies under what files (partitions) to run the data quality and transform processes. This ties DIRECTLY to the[ Authoring Plugins](https://docs.perigee.software/transform-sdk/authoring-plugins) section about partition keys as these partitions are assigned at the class and attribute level of the defined checks, and they must match what is assigned here.&#x20;

If a blank is used in the processes partition keys, assigning a blank here will also run that process.&#x20;

* Blank <mark style="color:red;">**`""`**</mark> values are typically used for "global" processes.
* Friendly key names, like <mark style="color:red;">**`"finance"`**</mark> may be used to group certain processes only when running financial files
* The  [DataTable (Transform Group)](https://docs.perigee.software/transforms/the-mapping-document#transformgroup) name can be put in the comma separated list of partitions when authoring plugins. This is how **`AutoAddMapToPartitionKeys`** is able to automatically add the partition keys to the registered keys and run additional processes.&#x20;
  {% endhint %}

```csharp
//Define custom transforms: 
//  - Transform colID 1 ToUpper
var customConversions = new Dictionary<int, Func<object, object, DataRow, MappingColumn, long, object>> {
        { 1, (value, defaultValue, row, map, index) => value?.ToString()?.ToUpper() ?? defaultValue }
    };
    
var result = new DataTable().MapTo(
    Transformer.GetMapFromFile("map.xlsx", out var mreport).FirstOrDefault(),
    Transformer.ToGroupHash(Transformer.GetLookupFromFile("lookups.csv", out var lreport)), 
    CustomConversions: customConversions,
    OnBeforeTableAdd: row => { row["Status"] = "New"; },

    DataQualityModules: DataQuality.GetModules(),
    DataQualityPartitionKeys: new List<string>() { "general", "" },
    TransformProcessModules: TransformationProcess.GetModules(),
    TransformProcessPartitionKeys: new List<string>() { "general", "" },
    AutoAddMapToPartitionKeys: true);
```

### What about File IO Plugins?

To run File IO Processes, see the[ plugin authoring page](https://docs.perigee.software/authoring-plugins/file-io-process#running-fiops-manually-sdk) as they are run before any of the <mark style="color:purple;">**`MapTo`**</mark> processes start. You'll need to decide which File IO Processes to run manually as they can drastically change the data being processed.&#x20;
