Ir para o conteúdo

Scripting Example - Custom Excel Import

This plugin is designed to import a formatted excel document.

It allows for data indented 1 column in, ignoring title formatting before getting to headers, header fields which span 2 rows, skips over rows with subtotals/grand total, and ignores an existing footer. On Business Object running event:

BusinessObjectID provides the TableID of target for imported data.

File provides the file to be imported (binary data field)

AttachmentID and AttachmentTypeID: GUIDs to identify source of imported data

if (columnName == "Billing") //where "Billing" is the value in second column for the beginning of first header row.

if (firstColumnName == "Grand Total:") //first column first row value after all records of desired imported data

if (SecondColumnName == "Invoice Number:") //first column value of last row of title data before first header rowAt the bottom, target columns get matched to a count of the column number of excel for source data. i.e. the following line will indicate to get the 10th column of data and insert it into the "Product" field in target Business Object

Use Case

This could be used when another service or an internal business process is managed via a formatted excel, that is maintained and later needs to be ingested into Vinyl as a data source for a on-going business process. This is helpful during a transition when a business process is replaced in Vinyl in portions, rather than its entirety at once, and this is becomes the best option to ensure accurate and seamless continuity of data with no additional steps for the business to format data before bringing into Vinyl for updated processes.

Plugin References

Column Data Type Description
BusinessObjectID Unique ID provides the TableID of target for imported data
File binary data field provides the file to be imported
AttachmentID Unique ID identify source of imported data
AttachmentTypeID Unique ID identify source of imported data

Custom Excel Import Script

#r "ExcelDataReader.dll"
using ExcelDataReader;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Vinyl.Sdk.Filtering;
// TARGET
// The MRP table it will populate
string strBusinessObjectID;
strBusinessObjectID = Row["BusinessObjectID"].Value.ToString();
Guid targetMRPTableId = Guid.Parse(strBusinessObjectID);
// SOURCE
// File to be imported
var file = (byte[])Row["File"].Value;
string strAttachmentID;
strAttachmentID = Row["AttachmentID"].Value.ToString();
string strAttachmentTypeID;
strAttachmentTypeID = Row["AttachmentTypeID"].Value.ToString();
//Guid attachmentID = Guid.Parse(strAttachmentID);
// SERVICES
var tableService = Services.GetService<ITableService>();
var eventService = Services.GetService<IEventService>();
// EVENT TABLES
var mrpTable = await GetEventTable(eventService, tableService, targetMRPTableId);
// Read file
using (var stream = new MemoryStream(file))
{
    using (var reader = ExcelReaderFactory.CreateReader(stream))
    {
        // Generates the Primary Key for the SRP as it will also be used as a FK
        // on the MRP
        //var id = Guid.Parse(strAttachmentID);
        await ConsumeMRP(eventService, mrpTable, reader, strAttachmentID, strAttachmentTypeID);
    }
}
/// <sumary>
/// For a given table id, returns its EventTable
/// </sumary>
private async Task<EventTable> GetEventTable(
    IEventService eventService, 
    ITableService tableService, 
    Guid tableId) 
{
    // This workaround is not needed anymore in the latest 2.7 hotfix
    // but anything before then, to get the EventTable from a given
    // tableId, we need to raise a filter event with no rows
    var table = tableService.GetTable(tableId);
    var filter = table.CreateFilter();
    filter.Limit = 0;

    var eventTable = await eventService.InvokeFilterEventAsync(filter);
    return eventTable;
}
/// <sumary>
/// Tries to set a cell value, checking if column is available first
/// </sumary>
private void TrySetValue(EventRow row, string columnName, object value) 
{
    if (row.TryGetCell(columnName, out EventCell cell)) 
    {
        cell.Value = value;
    }
}
private string GetColumnName(object value)
{
    string str = Convert.ToString(value ?? "");
    str = Regex.Replace(str, " *[\r\n]+", " ");
    return str.Trim();
}
/// <sumary>
/// Populate the MRP until the first cell is empty
/// </sumary>
private async Task ConsumeMRP(
    IEventService eventService,
    EventTable importTable,
    IExcelDataReader reader,
    string attachmentID,
    string attachmentTypeID)
    {
    while(reader.Read()) 
    {
        var columnName = reader
            .GetValue(1)?
            .ToString()
            .Replace(":", "")
            .Trim();

        if (columnName == "Billing") {
            // MRP started
            break;
        }
    }


    var fields = new List<string>();

        for (var index = 1; index < reader.FieldCount; index++)
        {
            fields.Add(GetColumnName(reader.GetValue(index)));
        }
    if (!reader.Read()) 
    {
        // MRP cut short? Throw exception?
        return;
    }
    // Append sub-title
    for (var index = 0; index < fields.Count; index++)
    {
            if (!reader.IsDBNull(index+1))
            {
                fields[index] += " " + GetColumnName(reader.GetValue(index+1));
            }
    }

    int rowcount= 0;

    while(reader.Read()) 
    {
        rowcount = rowcount+1;
        string SecondColumnName=""; 
        string firstColumnName="";

            if(! reader.IsDBNull(1))    
            { 
                SecondColumnName = reader.GetValue(1).ToString().Trim();   
            }
            else
            {
                SecondColumnName ="";
            }
            if(! reader.IsDBNull(0))    
            { 
                firstColumnName = reader.GetValue(0).ToString();   
            }
            else
            {
                firstColumnName="";
            }



        if (firstColumnName == "Grand Total:")
        {
            break;
        }
        if (SecondColumnName == "Invoice Number:")
        {
            continue;
        }
        if (SecondColumnName == "")
        {
            continue;
        }

            // Creates a new row in the staging table
            var dataRow = await eventService.InvokeNewEventAsync(importTable);

            dataRow["stGarnishmentID"].Value = Guid.NewGuid();
            dataRow["AttachmentID"].Value = attachmentID;
            dataRow["AttachmentTypeID"].Value = attachmentTypeID;
            //testRow6["Product"].Value = reader.GetValue(10);
         //   await eventService.InvokeInsertEventAsync(testRow6);

            //row["Invoice Number"].Value=reader.GetValue(1);

            for (var index = 0; index < fields.Count; index++)
            {
                var columnName = fields[index];
                var value = Convert.ToString(reader.GetValue(index+1));
                TrySetValue(dataRow, columnName, value);
            }
         await eventService.InvokeInsertEventAsync(dataRow);



    }

}