cancel
Showing results for 
Search instead for 
Did you mean: 

Upgrade from 6.5 to 7.3 BluePrism.AutomateProcessCore.dll not having the DataType function

Alot of our custom object now have compile errors in version 7.3 due to the below error. Does anyone know what the new "function" for DataType is within the AutomateProcessCore.dll for 7.3? I cant see any comparable type that i can update the code to use. Any help would be greatly appreciated.

 

Page: Initialise
Stage: Stage1
Type: Error
Action: Validate
Description: Compiler error at line 80: The type or namespace name 'DataType' does not exist in the namespace 'BluePrism.AutomateProcessCore' (are you missing an assembly reference?)
Repairable: No

Example of how it is being used currently:

DataTable In2 = FixTimeIssue(Input, BPVersionMajor);
DataTable data;
ExtractSingleColumn(In2, Column_Name, out data);
// Add a count row
DataColumn col = new DataColumn("Count", typeof(Decimal));
col.ExtendedProperties.Add("bptype", BluePrism.AutomateProcessCore.DataType.number);
data.Columns.Add(col);
foreach (DataRow row in data.Rows)
{
row[col] = 1;
}
// Now collapse the table to sum the rows
Output = CollapseTable(data, new List<String>(){Column_Name}, new List<String>(){"Count"});

 

 

7 REPLIES 7

naveed_raza
Level 7

upgrading from 6.5 to 7.x , Blueprism.automateprocesscore.datatype related error is common, its mainly due to internal library changes.

In BP 7.x core assemblies, namespaces and internal DLL structures probably got changed

- AutomateProcessCore.dll fefactored

- DataType handling engine modified

- Some DataType classes moved or renamed

- New Unicode + .Net 4.8 compatibility updates

Hi Naveed,

Thanks for your response. Do you have any ideas on how to resolve this error? Is there another function in the updated dll i can reference that will accomplish the same thing?

naveed_raza
Level 7

One thing i can say is, try to re-import the release and see

Michael_S
Community Team
Community Team

@david.l.morris - am I right in thinking you migrated to 7.3? Did you experience anything similar?

@TrevorMclellan21 Change this line:

col.ExtendedProperties.Add("bptype", BluePrism.AutomateProcessCore.DataType.number);

To this:
col.ExtendedProperties.Add("bptype", BluePrism.AutomateProcessCore.ProcessDataTypes.DataTypeId("number"));

I only tested part of your code since I don't know what those other functions do, but this works to add a number datatype field to a DataTable. I'm not sure what the difference is between that and a Decimal DataType as I would assume this is the same thing, but I'm just suggesting this so you are able to adjust your existing code as minimally as possible. Let me know if you still have an issue.

Note that if you test this outside of Blue Prism, you may also have to add BluePrism.Core.dll as a reference, but at least in 7.5 I didn't have to add that separately as a reference in the object. It worked for me to simply change the one line above.

@Michael_S Thanks for the ping. We did upgrade through 6.5 -> 6.10 -> 7.3 -> 7.4 -> 7.5 in our evaluation environment, but I hadn't run into this. I just assumed Blue Prism likely reorganized some things in the code and glanced around a bit to find that the code should work with that small adjustment.


Dave Morris, 3Ci at Southern Company

Hi David,

This worked! Thanks! Unfortunately i have now discovered another object which is using this datatype field and it is much more complex. Its being used in the global code section and I have tried to update it the same way I did the other actions but I am getting a bunch of new errors such as the ones seen in the attached screenshot.

TrevorMclellan21_0-1765470739547.png

Below I have copied the code from before my edits. I did not write this code but the main purpose of this object is to read CSVs. I have a feeling something to do with the dictionaries is breaking it but I'm really not sure. Any help on this would be awesome.

 

 

static DataTable FixTimeIssue(DataTable table, Decimal BPVersionMajor) // from Collection Storage object
{
if (BPVersionMajor != 5)
return table;
Boolean needsFixing = false;
foreach (DataColumn col in table.Columns)
{
if (col.DataType.Equals(typeof(DateTime)))
needsFixing = true;
}
if (!needsFixing)
return table;            
 
DataRow newRow;
 
DataTable result = new DataTable();
result.TableName = table.TableName;
 
foreach (DataColumn col in table.Columns)
{
DataColumn newCol = new DataColumn(col.ColumnName, col.DataType);
if (col.ExtendedProperties.Contains("bptype"))
newCol.ExtendedProperties.Add("bptype", col.ExtendedProperties["bptype"]);
if (newCol.DataType.Equals(typeof(DateTime)))
{
newCol.DateTimeMode = DataSetDateTime.Utc;
}
result.Columns.Add(newCol);
}
 
foreach (DataRow row in table.Rows)
{
newRow = result.NewRow();
foreach (DataColumn col in table.Columns)
{
if (col.DataType.Equals(typeof(DateTime)))
{
newRow[col.ColumnName] = DateTime.SpecifyKind(Convert.ToDateTime(row[col.ColumnName]), DateTimeKind.Utc);
}
else
{
newRow[col.ColumnName] = row[col.ColumnName];
}
}
result.Rows.Add(newRow);
}
return result;
}
static Dictionary<String, BluePrism.AutomateProcessCore.DataType> string2BpType = new Dictionary<String, BluePrism.AutomateProcessCore.DataType>()
{
{"collection", BluePrism.AutomateProcessCore.DataType.collection},
{"date", BluePrism.AutomateProcessCore.DataType.date},
{"datetime", BluePrism.AutomateProcessCore.DataType.datetime},
{"flag", BluePrism.AutomateProcessCore.DataType.flag},
{"number", BluePrism.AutomateProcessCore.DataType.number},
{"password", BluePrism.AutomateProcessCore.DataType.password},
{"text", BluePrism.AutomateProcessCore.DataType.text},
{"time", BluePrism.AutomateProcessCore.DataType.time},
{"timespan", BluePrism.AutomateProcessCore.DataType.timespan},
};
static Dictionary<String, Type> string2CsType = new Dictionary<String, Type>()
{
{"collection", typeof(DataTable)},
{"date", typeof(DateTime)},
{"datetime", typeof(DateTime)},
{"flag", typeof(Boolean)},
{"number", typeof(Decimal)},
{"password", typeof(String)},
{"text", typeof(String)},
{"time", typeof(DateTime)},
{"timespan", typeof(DateTime)},
};
class TypeStruct
{
public BluePrism.AutomateProcessCore.DataType bptype;
public Type csType;
public Boolean couldBe;
public Regex regexTest;
public String formatString;
public Decimal typePriority;
public TypeStruct(BluePrism.AutomateProcessCore.DataType bpdatatype, Type datatype, String test, Decimal priority)
{
bptype = bpdatatype;
csType = datatype;
couldBe = true;
regexTest = new Regex(test);
formatString = "";
typePriority = priority;
}
public TypeStruct(BluePrism.AutomateProcessCore.DataType bpdatatype, Type datatype, String test, String format, Decimal priority)
{
bptype = bpdatatype;
csType = datatype;
couldBe = true;
regexTest = new Regex(test);
formatString = format;
typePriority = priority;
}
public override String ToString()
{
return "bptype: " + bptype.ToString() + " format: " + formatString + "valid?: " + couldBe.ToString();
}
}
class ColumnType
{
public String colName;
public BluePrism.AutomateProcessCore.DataType bptype;
public Type csType;
public String formatString;
public ColumnType(String columnName, TypeStruct columnType)
{
colName = columnName;
bptype = columnType.bptype;
csType = columnType.csType;
formatString = columnType.formatString;
}
public ColumnType(String columnName, String bptypeString, String formatCode)
{
colName = columnName;
bptype = string2BpType[bptypeString];
csType = string2CsType[bptypeString];
formatString = formatCode;
}
public override String ToString()
{
return "Col: " + colName + " bptype: " + bptype.ToString() + "Format: " + formatString;
}
}
class TypeFinder : IEnumerable<TypeStruct>
{
public List<TypeStruct> typeList;
public Int32 CountTypes()
{
Int32 counter = 0;
foreach (TypeStruct ts in typeList)
{
if (ts.couldBe)
counter ++;
}
return counter;
}
public TypeStruct GetDataType()
{
Int32 validTypeCount = CountTypes();
TypeStruct defaultType = new TypeStruct(BluePrism.AutomateProcessCore.DataType.text, typeof(String), @".*", 0);
if (validTypeCount == 0)
return defaultType;
else if (validTypeCount == 1)
{
foreach (TypeStruct ts in typeList)
{
if (ts.couldBe)
return ts;
}
throw new InvalidOperationException("TypeFinder.GetType - This code should be unreachable.");
}
else
return defaultType;
}
public TypeFinder()
{
typeList = new List<TypeStruct>(){
new TypeStruct(BluePrism.AutomateProcessCore.DataType.number, typeof(Decimal), @"^\d*$", 1),
new TypeStruct(BluePrism.AutomateProcessCore.DataType.flag, typeof(Boolean), @"^(True|true|False|false)?$", 1),
new TypeStruct(BluePrism.AutomateProcessCore.DataType.date, typeof(DateTime), @"^\d{4}-[01]\d-[0-3]\d$", @"yyyy-MM-dd", 10),
new TypeStruct(BluePrism.AutomateProcessCore.DataType.date, typeof(DateTime), @"^[01]\d\/[0-3]\d\/\d{4}$", @"dd/MM/yyyy", 10),
new TypeStruct(BluePrism.AutomateProcessCore.DataType.date, typeof(DateTime), @"^[0123]?\d\/[01]?\d\/\d{4}$", @"d/M/yyyy", 9),
new TypeStruct(BluePrism.AutomateProcessCore.DataType.date, typeof(DateTime), @"^[0123]\d\/[01]\d\/\d{4}$", @"MM/dd/yyyy", 8),
new TypeStruct(BluePrism.AutomateProcessCore.DataType.date, typeof(DateTime), @"^[01]?\d\/[0123]?\d\/\d{4}$", @"M/d/yyyy", 7),
new TypeStruct(BluePrism.AutomateProcessCore.DataType.datetime, typeof(DateTime), @"^\d{4}-[01]\d-[0-3]\d \d{2}:\d{2}$", @"yyyy-MM-dd hh:mm", 10),
new TypeStruct(BluePrism.AutomateProcessCore.DataType.datetime, typeof(DateTime), @"^\d{4}-[01]\d-[0-3]\d [0-2]\d:[0-5]\d:[0-5]\d$", @"yyyy-MM-dd HH:mm:ss", 10),
new TypeStruct(BluePrism.AutomateProcessCore.DataType.datetime, typeof(DateTime), @"^\d{4}-[01]\d-[0-3]\d [0-1]\d:[0-5]\d:[0-5]\d [AP]M$", @"yyyy-MM-dd hh:mm:ss tt", 10),
new TypeStruct(BluePrism.AutomateProcessCore.DataType.time, typeof(DateTime), @"^[0-2]\d:[0-5]\d$", @"HH:mm", 10),
new TypeStruct(BluePrism.AutomateProcessCore.DataType.time, typeof(DateTime), @"^[0-1]\d:[0-5]\d [AP]M$", @"hh:mm tt", 10),
new TypeStruct(BluePrism.AutomateProcessCore.DataType.time, typeof(DateTime), @"^[0-2]\d:[0-5]\d:[0-5]\d$", @"HH:mm:ss", 10),
new TypeStruct(BluePrism.AutomateProcessCore.DataType.time, typeof(DateTime), @"10:59:59 AM", @"hh:mm:ss tt", 10),
};
}
public IEnumerator<TypeStruct> GetEnumerator()
{
return typeList.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
 
}
 
static String NumberToLetters(Int32 number)
{
/*
Converts column numbers to Excel-style column labels (e.g. 1-> A, 2 -> B, 27 -> AA)
*/
Int32 colNum = Convert.ToInt32(number);
Int32 i3 = 0, i2 = 0, i1 = 0;
String s3 = "", s2 = "", s1 = "";
if (colNum > 0)
{
i1 = (colNum - 1) % 26;
s1 = ((char)(65 + i1)).ToString();
}
if (colNum > 26)
{
i2 = ( ( (colNum - i1) / 26 ) - 1 ) % 26;
s2 = ((char)(65 + i2)).ToString();
}
if (colNum > 702)
{
i3 = ( ( (colNum - i2 - i1) / 676 ) - 1) % 26;
s3 = ((char)(65 + i3)).ToString();
}
return s3 + s2 + s1;
}
 
static Char separatorChar =  ',';
 
static List<String> SplitLine(String content)
{
List<String> result = new List<String>();
List<Int32> separators = new List<Int32>();
separators.Add(-1);
Boolean inQuotes = false;
Int32 counter = 0;
foreach (Char c in content)
{
if (c == separatorChar)
{
if (!inQuotes)
separators.Add(counter);
}
else if (c == '"')
inQuotes = !inQuotes;
counter ++;
}
separators.Add(content.Length);
// We now have a list of every separator location.
// Now we can divide the string 
for (int i = 1; i < separators.Count; i++)
{
result.Add(content.Substring(separators[i - 1] + 1, separators[i] - separators[i - 1] - 1));
}
for (int i = 0; i < result.Count; i++)
{
String element = result[i];
Int32 length = element.Length;
Boolean changed = false;
// if it's surrounded with quotes remove those
if (element.Length >= 2 && element.Substring(0, 1) == @"""" && element.Substring(length - 1, 1) == @"""")
{
element = element.Substring(1, length - 2);
changed = true;
}
if (element.Contains(@""""""))
{
element = element.Replace(@"""""", @"""");
changed = true;
}
// if quotes are encoded as "" then change to a single "
if (changed)
result[i] = element;
 
}
return result;
}
static List<TypeStruct> DetermineListTypes(List<List<String>> content)
{
// assume that you pass in the data and not the column names
List<TypeStruct> result = new List<TypeStruct>();
Int32 rows = content.Count;
Int32 cols = content[0].Count;
List<TypeFinder> validTypes = new List<TypeFinder>();
for (int co = 0; co < cols; co++)
validTypes.Add(new TypeFinder());
for (int ro = 0; ro < rows; ro++) // for every row in data
{
List<String> currentRow = content[ro];
if (!currentRow.Count.Equals(cols))
throw new InvalidDataException("inconsistent number of rows");
for (int co = 0; co < cols; co++) //  for every column in data (column 0 is headers)
{
String cellContents = currentRow[co];
// Console.WriteLine("Working on item: " + cellContents);
TypeFinder tf = validTypes[co];
for (int t = 0; t < tf.typeList.Count; t++) // for every data type
{
TypeStruct ts = tf.typeList[t];
if (ts.couldBe) // if that data types hasn't yet been excluded
{
// Console.Write("Testing TypeStruct: " + ts.ToString() + " ... ");
if (!ts.regexTest.IsMatch(cellContents)) // check the contents against all the data types not yet excluded
{
ts.couldBe = false; // if it couldn't be that then exclude that type
// Console.WriteLine("False");
}
else
{
// Console.WriteLine("True");
}
}
}
}
}
for (int co = 0; co < cols; co++)
{
result.Add(validTypes[co].GetDataType());
}
// I now have a list of TypeStruct, 1 per column, that contain all of the data types that the columm could be.
return result;
}
static List<ColumnType> DetermineColumnTypes(List<String> columns, List<List<String>> content)
{
List<ColumnType> columnTypes = new List<ColumnType>();
List<TypeStruct> listTypes = DetermineListTypes(content);
for (int i = 0; i < columns.Count; i++)
{
columnTypes.Add(new ColumnType(columns[i], listTypes[i])); 
}
return columnTypes;
}
static List<ColumnType> DetermineColumnTypes(List<String> columns, List<List<String>> content, List<ColumnType> hints)
{
List<ColumnType> columnTypes = new List<ColumnType>();
List<String> hintColumns = hints.Select(x => x.colName).ToList();
// if hints already has all the info then we don't need to parse the data
if (columns.OrderBy(x => x).SequenceEqual(hints.Select(x => x.colName).OrderBy(x => x)))
{
for (int i = 0; i < columns.Count; i++)
{
if (hintColumns.Contains(columns[i]))
columnTypes.Add(hints.Where(x => x.colName == columns[i]).First());
}
return columnTypes;
}
// otherwise we need to parse the data
List<TypeStruct> listTypes = DetermineListTypes(content);
for (int i = 0; i < columns.Count; i++)
{
if (hintColumns.Contains(columns[i]))
columnTypes.Add(hints.Where(x => x.colName == columns[i]).First());
else
columnTypes.Add(new ColumnType(columns[i], listTypes[i])); 
}
return columnTypes;
}
static List<ColumnType> GiveStringColumnTypes(List<String> columns, List<List<String>> content)
{
List<ColumnType> columnTypes = new List<ColumnType>();
TypeStruct stringTypeStruct = new TypeStruct(BluePrism.AutomateProcessCore.DataType.text, typeof(String), "^.*$", 99);
for (int i = 0; i < columns.Count; i++)
{
columnTypes.Add(new ColumnType(columns[i], stringTypeStruct));
}
return columnTypes;
}
static List<ColumnType> GiveStringColumnTypes(List<String> columns, List<List<String>> content, List<ColumnType> hints)
{
List<ColumnType> columnTypes = new List<ColumnType>();
List<String> hintColumns = hints.Select(x => x.colName).ToList();
TypeStruct stringTypeStruct = new TypeStruct(BluePrism.AutomateProcessCore.DataType.text, typeof(String), "^.*$", 99);
// if hints already has all the info then we don't need to parse the data
if (columns.OrderBy(x => x).SequenceEqual(hints.Select(x => x.colName).OrderBy(x => x)))
{
for (int i = 0; i < columns.Count; i++)
{
if (hintColumns.Contains(columns[i]))
columnTypes.Add(hints.Where(x => x.colName == columns[i]).First());
}
return columnTypes;
}
// otherwise we need to parse the data
for (int i = 0; i < columns.Count; i++)
{
if (hintColumns.Contains(columns[i]))
columnTypes.Add(hints.Where(x => x.colName == columns[i]).First());
else
columnTypes.Add(new ColumnType(columns[i], stringTypeStruct));
}
return columnTypes;
}
static Object ParseString(Type targetType, String content, String formatHelper)
{
if (targetType == typeof(String))
return content;
else if (targetType == typeof(Decimal))
{
return Convert.ToDecimal(content);
}
else if (targetType == typeof(Boolean))
{
return Convert.ToBoolean(content);
}
else if (targetType == typeof(DateTime))
{
if (formatHelper != "")
return DateTime.ParseExact(content, formatHelper, System.Globalization.CultureInfo.CurrentCulture);
else
return DateTime.Parse(content);
}
else
throw new Exception();
}
static System.Data.DataTable ParseFormats(List<ColumnType> columns, List<List<String>> content)
{
List<String> rowCells;
DataTable result = new DataTable();
for (int co = 0; co < columns.Count; co++)
{
DataColumn c = new DataColumn(columns[co].colName, columns[co].csType);
c.ExtendedProperties.Add("bptype", columns[co].bptype);
result.Columns.Add(c);
}
for (int ro = 0; ro < content.Count; ro++)
{
rowCells = content[ro];
DataRow newRow = result.NewRow();
Int32 minColumns = System.Math.Min(rowCells.Count, columns.Count);
for (int co = 0; co < minColumns; co++)
{
ColumnType ct = columns[co];
newRow[ct.colName] = ParseString(ct.csType, rowCells[co], ct.formatString);
}
result.Rows.Add(newRow);
}
return result;
}
static System.Data.DataTable ParseFormats(List<String> columns, List<List<String>> content, List<TypeStruct> typeList)
{
List<String> rowCells;
DataTable result = new DataTable();
for (int co = 0; co < columns.Count; co++)
{
DataColumn c = new DataColumn(columns[co], typeList[co].csType);
c.ExtendedProperties.Add("bptype", typeList[co].bptype);
result.Columns.Add(c);
}
for (int ro = 0; ro < content.Count; ro++)
{
rowCells = content[ro];
DataRow newRow = result.NewRow();
Int32 minColumns = System.Math.Min(rowCells.Count, columns.Count);
for (int co = 0; co < minColumns; co++)
{
TypeStruct ts = typeList[co];
newRow[columns[co]] = ParseString(ts.csType, rowCells[co], ts.formatString);
}
result.Rows.Add(newRow);
}
return result;
}
 
static void StreamToColumnsAndContent(StreamReader stream, out List<String> columns, out List<List<String>> content)
{
content = new List<List<String>>();
List<String> line;
String rawLine;
while ((rawLine = stream.ReadLine()) != null)
{
line = SplitLine(rawLine);
// Console.WriteLine("Cols in row: " + line.Count);
content.Add(line);
}
if (content.Count == 0)
{
columns = new List<String>();
content = new List<List<String>>();
}
else
{
columns = content[0];
content.RemoveAt(0);
}
}
 
static void StreamToColumnsAndContent(StreamReader stream, Boolean hasHeaders, Decimal skipRows, out List<String> columns, out List<List<String>> content)
{
content = new List<List<String>>();
List<String> line;
String rawLine;
Int32 skippedRows = 0;
while ((rawLine = stream.ReadLine()) != null)
{
if (skipRows > skippedRows)
{
skippedRows ++;
continue;
}
line = SplitLine(rawLine);
// Console.WriteLine("Cols in row: " + line.Count);
content.Add(line);
}
if (content.Count == 0)
{
columns = new List<String>();
// content = new List<List<String>>();
}
else
{
if (hasHeaders)
{
columns = content[0];
content.RemoveAt(0);
}
else
{
columns = new List<String>();
Int32 counter = 0;
foreach (String column in content[0])
{
counter ++;
columns.Add(NumberToLetters(counter));
}
}
}
}
 
static void StreamToColumnsAndContent(StreamReader stream, Boolean hasHeaders, Decimal skipRows, Decimal columnCount, out List<String> columns, out List<List<String>> content)
{
content = new List<List<String>>();
List<String> line;
String rawLine;
Int32 skippedRows = 0;
while ((rawLine = stream.ReadLine()) != null)
{
if (skipRows > skippedRows)
{
skippedRows ++;
continue;
}
line = SplitLine(rawLine);
// Console.WriteLine("Cols in row: " + line.Count);
content.Add(line);
}
if (content.Count == 0)
{
columns = new List<String>();
// content = new List<List<String>>();
}
else
{
if (hasHeaders)
{
columns = content[0];
content.RemoveAt(0);
}
else
{
columns = new List<String>();
for (int i = 1; i <= Convert.ToInt32(columnCount); i++)
{
columns.Add(NumberToLetters(i));
}
}
}
}
 
static DataTable StreamToTypedDataTable(StreamReader stream)
{
List<List<String>> content;
List<String> columns;
DataTable result;
StreamToColumnsAndContent(stream, out columns, out content);
List<ColumnType> colTypes = DetermineColumnTypes(columns, content);
result = ParseFormats(colTypes, content);
return result;
}
static DataTable StreamToTypedDataTable(StreamReader stream, List<ColumnType> hints)
{
List<List<String>> content;
List<String> columns;
DataTable result;
StreamToColumnsAndContent(stream, out columns, out content);
List<ColumnType> colTypes = DetermineColumnTypes(columns, content, hints);
result = ParseFormats(colTypes, content);
return result;
}
 
static DataTable StreamToStringDataTable(StreamReader stream)
{
List<List<String>> content;
List<String> columns;
DataTable result;
StreamToColumnsAndContent(stream, out columns, out content);
List<ColumnType> colTypes = GiveStringColumnTypes(columns, content);
result = ParseFormats(colTypes, content);
return result;
}
static DataTable StreamToStringDataTable(StreamReader stream, List<ColumnType> hints)
{
List<List<String>> content;
List<String> columns;
DataTable result;
StreamToColumnsAndContent(stream, out columns, out content);
List<ColumnType> colTypes = GiveStringColumnTypes(columns, content, hints);
result = ParseFormats(colTypes, content);
return result;
}
 
static DataTable StreamToStringDataTable(StreamReader stream, List<ColumnType> hints, Boolean hasHeaders, Decimal skipRows)
{
List<List<String>> content;
List<String> columns;
DataTable result;
StreamToColumnsAndContent(stream, hasHeaders, skipRows, out columns, out content);
List<ColumnType> colTypes = GiveStringColumnTypes(columns, content, hints);
result = ParseFormats(colTypes, content);
return result;
}
 
static DataTable StreamToStringDataTable(StreamReader stream, List<ColumnType> hints, Boolean hasHeaders, Decimal skipRows, Decimal columnCount)
{
List<List<String>> content;
List<String> columns;
DataTable result;
StreamToColumnsAndContent(stream, hasHeaders, skipRows, columnCount, out columns, out content);
List<ColumnType> colTypes = GiveStringColumnTypes(columns, content, hints);
result = ParseFormats(colTypes, content);
return result;
}
 
static List<ColumnType> HintsToColumnTypeList(DataTable hints)
{
// hint should contain
// Column Name
// Data Type
// Format Code
// in that order, all text
List<ColumnType> result = new List<ColumnType>();
foreach (DataRow row in hints.Rows)
{
String name = Convert.ToString(row[0]);
String bptype = Convert.ToString(row[1]);
String format = "";
if (hints.Columns.Count > 2)
format = Convert.ToString(row[2]);
result.Add(new ColumnType(name, bptype, format));
}
return result;
}
static DataTable FileAndHintsToTypedTable(String filename, DataTable hints)
{
List<ColumnType> hintList = HintsToColumnTypeList(hints);
using (StreamReader sr = new StreamReader(filename))
{
return StreamToTypedDataTable(sr, hintList);
}
}
static DataTable FileAndHintsToStringTable(String filename, DataTable hints)
{
List<ColumnType> hintList = HintsToColumnTypeList(hints);
using (StreamReader sr = new StreamReader(filename))
{
return StreamToStringDataTable(sr, hintList);
}
}
static DataTable FileAndHintsToTypedTableV2(String filename, DataTable hints)
{
List<ColumnType> hintList = HintsToColumnTypeList(hints);
using (FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
using (StreamReader sr = new StreamReader(fs))
{
return StreamToTypedDataTable(sr, hintList);
}
}
}
static DataTable FileAndHintsToStringTableV2(String filename, DataTable hints)
{
List<ColumnType> hintList = HintsToColumnTypeList(hints);
using (FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
using (StreamReader sr = new StreamReader(fs))
{
return StreamToStringDataTable(sr, hintList);
}
}
}
 
static DataTable FileAndHintsAndOptionsToStringTable(String filename, DataTable hints, Boolean hasHeaders, Decimal skipRows)
{
List<ColumnType> hintList = HintsToColumnTypeList(hints);
using (FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
using (StreamReader sr = new StreamReader(fs))
{
return StreamToStringDataTable(sr, hintList, hasHeaders, skipRows);
}
}
}
 
static DataTable FileAndHintsAndOptionsToStringTable(String filename, DataTable hints, Boolean hasHeaders, Decimal skipRows, Decimal columnCount)
{
List<ColumnType> hintList = HintsToColumnTypeList(hints);
using (FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
using (StreamReader sr = new StreamReader(fs))
{
return StreamToStringDataTable(sr, hintList, hasHeaders, skipRows, columnCount);
}
}
}
 
/*
================================================================================
#     # ######  ### ####### ### #     #  #####  
#  #  # #     #  #     #     #  ##    # #     # 
#  #  # #     #  #     #     #  # #   # #       
#  #  # ######   #     #     #  #  #  # #  #### 
#  #  # #   #    #     #     #  #   # # #     # 
#  #  # #    #   #     #     #  #    ## #     # 
## ##  #     # ###    #    ### #     #  #####  
================================================================================
*/
static String EncodeColumnName(String input, String separator)
{
String content = input;
if (content.Contains(@""""))
content = content.Replace(@"""", @"""""");
if (content.Contains(@"""") | content.Contains(separator))
{
content = @"""" + content + @"""";
}
return content;
}
static String EncodeText(String input)
{
return @"""" + input.Replace(@"""", @"""""") + @"""";
}
static String EncodeText(String input, String separator)
{
String content = input;
if (content.Contains(@""""))
content = content.Replace(@"""", @"""""");
if (content.Contains(@"""") | content.Contains(separator))
{
content = @"""" + content + @"""";
}
return content;
}
static List<String> DataTableToStringList(DataTable table, String separator)
{
List<String> content = new List<String>();
List<String> rowCells = new List<String>();
String bptype;
foreach (DataColumn col in table.Columns)
rowCells.Add(EncodeColumnName(col.ColumnName, separator));
content.Add(String.Join(separator, rowCells));
foreach (DataRow row in table.Rows)
{
rowCells = new List<String>();
foreach (DataColumn col in table.Columns)
{
if (col.ExtendedProperties.Contains("bptype"))
{
bptype = col.ExtendedProperties["bptype"].ToString();
if (bptype == "text")
rowCells.Add(EncodeText(row[col].ToString(), separator));
else if (bptype == "date")
rowCells.Add(Convert.ToDateTime(row[col]).ToString("yyyy-MM-dd"));
else if (bptype == "datetime")
rowCells.Add(Convert.ToDateTime(row[col]).ToString("yyyy-MM-dd hh:mm:ss tt"));
else if (bptype == "time")
rowCells.Add(Convert.ToDateTime(row[col]).ToString("hh:mm:ss tt"));
else
rowCells.Add(row[col].ToString());
}
else
{
if (col.DataType == typeof(String))
rowCells.Add(EncodeText(row[col].ToString()));
else if (col.DataType == typeof(Decimal))
rowCells.Add(row[col].ToString());
else if (col.DataType == typeof(DateTime))
rowCells.Add(Convert.ToDateTime(row[col]).ToString("yyyy-MM-dd hh:mm:ss tt"));
else
rowCells.Add(row[col].ToString());
}
}
content.Add(String.Join(separator, rowCells));
}
return content;
}
static void DataTableToStream(DataTable input, StreamWriter sw, String separator)
{
List<String> content = DataTableToStringList(input, separator);
Int32 lines = content.Count;
for (Int32 i = 0; i < lines; i++)
{
if (i < lines - 1)
sw.WriteLine(content[i]);
else
sw.Write(content[i]);
}
}
static void DataTableToFile(DataTable input, String filename, Decimal BPVersionMajor)
{
DataTable content = FixTimeIssue(input, BPVersionMajor);
using (StreamWriter sw = new StreamWriter(filename))
{
DataTableToStream(content, sw, ",");
}
}
 
static void DataTableToFileChunk(DataTable input, String filename, Decimal BPVersionMajor)
{
    // Fix time issues in the input collection
    DataTable content = FixTimeIssue(input, BPVersionMajor);
 
    // Define the chunk size
    int chunkSize = 50000;
 
    // Get the total number of rows in the DataTable
    int totalRows = content.Rows.Count;
 
    // Open the StreamWriter for writing to the file
    using (StreamWriter sw = new StreamWriter(filename))
    {
        // Write the column headers to the file
        string[] columnNames = new string[content.Columns.Count];
        for (int i = 0; i < content.Columns.Count; i++)
        {
            columnNames[i] = content.Columns[i].ColumnName;
        }
        sw.WriteLine(string.Join(",", columnNames)); // Write headers as the first row
 
        // Process the DataTable in chunks
        for (int startRow = 0; startRow < totalRows; startRow += chunkSize)
        {
            // Get the current chunk of rows
            int endRow = Math.Min(startRow + chunkSize, totalRows);
 
            for (int i = startRow; i < endRow; i++)
            {
                // Write each row to the file
                string[] rowValues = new string[content.Columns.Count];
                for (int j = 0; j < content.Columns.Count; j++)
                {
                    // Handle null values and format data to avoid breaking the CSV structure
                    if (content.Rows[i][j] != null)
                      {
                        rowValues[j] = content.Rows[i][j].ToString()
                        .Replace("\n", "")  // Remove newline
                        .Replace("\r", ""); // Remove carriage return
                      }
                    else
                      {
                        rowValues[j] = string.Empty;
                      }
                }
                sw.WriteLine(string.Join(",", rowValues));
            }
        }
    }
}
 
 
 
static void DataTableToFileUnsafe(DataTable input, String filename)
{
System.GC.Collect(2, System.GCCollectionMode.Forced, true);
Int32 writerCounter = 0;
Boolean first;
String colType;
using (StreamWriter sw = new StreamWriter(filename))
{
// write columns
first = true;
foreach (DataColumn c in input.Columns)
{
if (first)
first = false;
else
sw.Write(",");
sw.Write(c.ColumnName);
}
sw.WriteLine();
// write data
foreach (DataRow r in input.Rows)
{
first = true;
foreach (DataColumn c in input.Columns)
{
if (first)
first = false;
else
sw.Write(",");
if (c.ExtendedProperties.Contains("bptype"))
colType = c.ExtendedProperties["bptype"].ToString();
else
colType = "unknown";
if (colType == "text")
sw.Write(EncodeText((String) r[c]));
else if (colType == "password")
sw.Write(EncodeText((String) r[c]));
else if (colType == "number")
sw.Write(((Decimal) r[c]).ToString());
else if (colType == "date")
sw.Write(((DateTime) r[c]).ToString("yyyy-MM-dd"));
else if (colType == "time")
sw.Write(((DateTime) r[c]).ToString("hh:mm:ss tt"));
else if (colType == "datetime")
sw.Write(((DateTime) r[c]).ToString("yyyy-MM-dd hh:mm:ss tt"));
else // unknown
sw.Write(EncodeText(Convert.ToString(r[c])));
}
sw.WriteLine();
writerCounter ++;
if (writerCounter > 10000)
{
System.GC.Collect(2, System.GCCollectionMode.Forced, true); 
writerCounter = 0;
}
}
}
System.GC.Collect(2, System.GCCollectionMode.Forced, true); 
}

 

I think it would be worth having a developer redesign this to try using one of the standard objects in order to read a CSV. It may be necessary to do it like this, but I wonder if it is still necessary or not. That is a lot of code to do something that we usually don't need special logic for. Of course I'm just making a guess here without any real context.

If you are for sure trying to keep all that code, I would imagine you can fix it quite quickly and easily using Cursor or GitHub Copilot. The AI agents designed for writing code are specifically really good at fixing code when they have a reference. In this case, you'd have a project where you drop that code in and then add references to the various Blue Prism DLL files, and then ask the LLM to figure out what should be changed based on the available classes and functions in the new DLL files.

Is this something you or someone on your team is comfortable trying to do?


Dave Morris, 3Ci at Southern Company