how to seek position in datatable before writing to the file - c#-3.0

I have the data table that is read from csv file. Then it is iterated through row and columns, and each value is appended before writing to the file that is also destination csv file. I want to separate the data of one column upon the special character ("/"), into two columns. For example, the column of 'Type' of data table is "women/shoes and handbags/guess". I have another column 'SubType', so I want to separate one column to two columns in data table before writing. I just want to ignore third type that is guess. Is there a way to seek position "/" and after second "/", I want to insert that value into another column of data table that is 'SubType'.
foreach (DataRow dRow in dtSor.Rows)
{
for (int i = 0; i < dtSor.Columns.Count; i++)
{
if (dRow[i].ToString().Contains(","))
{
dest_csv.Append("\"" + dRow[i].ToString() + "\"" + ",");
}
else if (dRow[i].ToString() == "")
{
dest_csv.Append("NULL" + ",");
}
else
{
dest_csv.Append(dRow[i].ToString() + ",");
//dest_csv.Append(dRow[i].ToString());
}
}
dest_csv.Remove(dest_csv.Length - 1, 1);
dest_csv.Append(Environment.NewLine);
}
File.WriteAllText(destination_file, dest_csv.ToString(), Encoding.Default);
}

First check if the special char is in the field with indexOf, then split the field on the special char in an araay and take only the parts you're intereseted in.
like so:
const char special = '\\';
string maintype ="";
string subtype ="";
string field = dRow[i].ToString();
if (field.IndexOf(special)>-1)
{
string[] splitted = field.Split(special);
maintype = splitted[0];
subtype = splitted[1];
}

Related

Convert List to json object in Talend

I'm trying to convert list result from tJava Component to json object.
Result from tjava component is below.
[{run_id=5d0753d58d93b71a1d12cc22_, parent_run_id=null, pipe_invoker=scheduled, path_id=shared, count=33, plex_path=null, invoker=abc.com, nested_pipeline=true, duration=355, start_time=2020-11-20T11:17:32.298000+00:00, lable=MP_SQS, state=Completed, key=57694b41ee, root_ruuid=2_ba32ea346}, {run_id=5bd4c6ea346, parent_run_id=null, pipe_invoker=scheduled, path_id=shared, count=33, plex_path=null, invoker=wwr.com, nested_pipeline=true, duration=355, start_time=2020-11-20T11:17:32.298000+00:00, lable=Summary_MP_SQS, state=Completed, key=55dfff4f, root_ruuid=1246d2-8bdc-1846}]
i tried using tConvertType, or in tMapper converting into String then replace all function multiple time and then storing result into json file but noting is working as expected.
End Expected result is json file from above result.
I don't think there is an easy way with a Talend component to do that (but I may be wrong :-) ) :
Put quotes on the keys/value
Replace "=" by ":"
But it can be done with regular Java code, here an example :
String input =
"[{run_id=1111, parent_run_id=null1, pipe_invoker=scheduled1, path_id=shared, count=33, plex_path=null}," +
" {run_id=2222, parent_run_id=null2, pipe_invoker=scheduled2, path_id=shared, count=33, plex_path=null}]";
StringBuilder output = new StringBuilder();
input = input.substring(2,input.length() - 2); // remove "[{" .... "}]"
output.append("[{");
String step1 [] = input.split("\\}, \\{"); // each record, split on "}, {"
int j = 1;
for (String record : step1) {
String step2 [] = record.split(","); // each key/value, split on ","
int i = 1;
for (String keyValue : step2) {
// key=value --> "key":"value"
output.append("\"" + keyValue.split("=")[0].trim() + "\":\"" + keyValue.split("=")[1].trim() + "\"");
if (i++ < step2.length ) {
output.append(",");
}
}
if (j++ < step1.length ) {
output.append("} , {");
}
}
output.append("}]");
/*
output :
[{"run_id":"1111","parent_run_id":"null1","pipe_invoker":"scheduled1","path_id":"shared","count":"33","plex_path":"null"} , {"run_id":"2222","parent_run_id":"null2","pipe_invoker":"scheduled2","path_id":"shared","count":"33","plex_path":"null"}]
*/

Sort table column with custom comparator

I have a table column which displays customers full names (first name + last name). However, I want to sort this column first by first name and then by last name. Therefore I added some comparator function in my controller:
_customNameComparator: function(value1, value2) {
// Separate all words of the full name
var aWordsName1 = value1.split(" ");
var aWordsName2 = value2.split(" ");
// Get the last and first names of the two names
var sFirstName1 = value1.substring(0, value1.lastIndexOf(" "));
var sLastName1 = aWordsName1[aWordsName1.length - 1];
var sFirstName2 = value2.substring(0, value1.lastIndexOf(" "));
var sLastName2 = aWordsName2[aWordsName2.length - 1];
// 0 values are equal
// -1 value1 smaller than value2
// 1 value1 larger than value2
if (sLastName1 === sLastName2) {
if (sFirstName1 === sFirstName2) {
return 0;
} else if (sFirstName1 > sFirstName2) {
return 1;
} else {
return -1;
}
} else if (sLastName1 > sLastName2) {
return 1;
} else {
return -1;
}
}
When the column Header is clicked, I try to call
var aSorter = [];
aSorter.push(new sap.ui.model.Sorter("FullName", bDescending, false, this._customNameComparator));
var oBinding = this.byId("tableTargetGroupDetails").getBinding("items");
oBinding.sort(aSorter);
The comparator does not work like this. The sorting is just as usual (by the full name). What do I do wrong?
And btw: I know that this can lead to some wrong sorting (e.g. for last names containing out of two or more words), but since it's "only" the sorting this is fine for me at the moment.
Unless your binding's operationMode is Client, your comparator will probably not work. You can set the mode where you do your binding using { parameters: { operationMode: 'Client' } }.

Ag-Grid - Pasting Excel Data into Grid - Appending Rows

When pasting clipboard/Excel data into AG-Grid, how do I get the data to append to the current rows?
If my table currently has a single row and I'm trying to paste 10 rows into the table, Ag-Grid only overwrites the single row instead of appending the extra 9 rows. Am I missing a gridOption or is this not possible?
To get what you need, follow these steps:
1) Add a paste event listener:
mounted () {
window.addEventListener('paste', this.insertNewRowsBeforePaste);
}
2) Create the function that retrieves the data from the clipboard and creates new lines in the grid:
insertNewRowsBeforePaste(event){
var self = this;
// gets data from clipboard and converts it to an array (1 array element for each line)
var clipboardData = event.clipboardData || window.clipboardData;
var pastedData = clipboardData.getData('Text');
var dataArray = self.dataToArray(pastedData);
// First row is already in the grid and dataToArray returns an empty row at the end of array (maybe you want to validate that it is actually empty)
for (var i = 1; i < dataArray.length-1; i++) {
self.addEmptyRow(i);
}
}
3) dataToArray is a function that ag-Grid uses to paste new lines and I just needed to adjust the "delimiter" variable. I copied it from the clipboardService.js file.
// From http://stackoverflow.com/questions/1293147/javascript-code-to-parse-csv-data
// This will parse a delimited string into an array of
// arrays. The default delimiter is the comma, but this
// can be overriden in the second argument.
export var dataToArray = function(strData) {
var delimiter = self.gridOptions.api.gridOptionsWrapper.getClipboardDeliminator();;
// Create a regular expression to parse the CSV values.
var objPattern = new RegExp((
// Delimiters.
"(\\" + delimiter + "|\\r?\\n|\\r|^)" +
// Quoted fields.
"(?:\"([^\"]*(?:\"\"[^\"]*)*)\"|" +
// Standard fields.
"([^\"\\" + delimiter + "\\r\\n]*))"), "gi");
// Create an array to hold our data. Give the array
// a default empty first row.
var arrData = [[]];
// Create an array to hold our individual pattern
// matching groups.
var arrMatches = null;
// Keep looping over the regular expression matches
// until we can no longer find a match.
while (arrMatches = objPattern.exec(strData)) {
// Get the delimiter that was found.
var strMatchedDelimiter = arrMatches[1];
// Check to see if the given delimiter has a length
// (is not the start of string) and if it matches
// field delimiter. If id does not, then we know
// that this delimiter is a row delimiter.
if (strMatchedDelimiter.length &&
strMatchedDelimiter !== delimiter) {
// Since we have reached a new row of data,
// add an empty row to our data array.
arrData.push([]);
}
var strMatchedValue = void 0;
// Now that we have our delimiter out of the way,
// let's check to see which kind of value we
// captured (quoted or unquoted).
if (arrMatches[2]) {
// We found a quoted value. When we capture
// this value, unescape any double quotes.
strMatchedValue = arrMatches[2].replace(new RegExp("\"\"", "g"), "\"");
}
else {
// We found a non-quoted value.
strMatchedValue = arrMatches[3];
}
// Now that we have our value string, let's add
// it to the data array.
arrData[arrData.length - 1].push(strMatchedValue);
}
// Return the parsed data.
return arrData;
}
4) Finally, to add new blank lines in the grid, use the function below:
addEmptyRow(rowIndex) {
var newItem = {};
this.gridOptions.api.updateRowData({add: [newItem], addIndex: rowIndex});
}
Basically what this code does is insert blank rows at the beginning of the grid and let ag-Grid paste the data into those rows. For it to work, the line where the code is pasted must be the first line in the grid. It's using the updateRowData from ag-grid (https://www.ag-grid.com/javascript-grid-data-update/).
You may need to make some adjustments if you need something else.
I have the same question. I originally used a paste event listener to add a number of rows to the grid, based on the difference between available space and clipboard data length. But now the grid will only add the rows and not complete the paste.

Parsing tab delimited file detect if first row value it empty/tab

Hi all I have a to parse some files to load into a DataSet and I ran into an issue where the first row value is sometimes blank so when I parse the data the rows added to the columns are off because there is no value for the row[RouteCode].
Example Data
Columns are in the first line(Tab delimited) DataRows are in the following rows(Tab delimited)
RouteCode City EmailAddress FirstName
NULL MyCity My-Email MyFirstName
What I am seeing is all the Columns are added fine but each row added the first tab value is not detected so it shifts the columns(hope I am making sense) so in this case the city data is sitting in the RouteCode column and the last column somehow is getting the first row value (tab).
class TextToDataSet
{
public TextToDataSet()
{ }
/// <summary>
/// Converts a given delimited file into a dataset.
/// Assumes that the first line
/// of the text file contains the column names.
/// </summary>
/// <param name="File">The name of the file to open</param>
/// <param name="TableName">The name of the
/// Table to be made within the DataSet returned</param>
/// <param name="delimiter">The string to delimit by</param>
/// <returns></returns>
public static DataSet Convert(string File,
string TableName, string delimiter)
{
//The DataSet to Return
DataSet result = new DataSet();
//Open the file in a stream reader.
using (StreamReader s = new StreamReader(File))
{
//Split the first line into the columns
string[] columns = s.ReadLine().Split(delimiter.ToCharArray());
//Add the new DataTable to the RecordSet
result.Tables.Add(TableName);
//Cycle the colums, adding those that don't exist yet
//and sequencing the one that do.
foreach (string col in columns)
{
bool added = false;
string next = "";
int i = 0;
while (!added)
{
//Build the column name and remove any unwanted characters.
string columnname = col + next;
columnname = columnname.Replace("#", "");
columnname = columnname.Replace("'", "");
columnname = columnname.Replace("&", "");
//See if the column already exists
if (!result.Tables[TableName].Columns.Contains(columnname))
{
//if it doesn't then we add it here and mark it as added
result.Tables[TableName].Columns.Add(columnname);
added = true;
}
else
{
//if it did exist then we increment the sequencer and try again.
i++;
next = "_" + i;
}
}
}
//Read the rest of the data in the file.
string AllData = s.ReadToEnd();
//Split off each row at the Carriage Return/Line Feed
//Default line ending in most windows exports.
//You may have to edit this to match your particular file.
//This will work for Excel, Access, etc. default exports.
string[] rows = AllData.Split("\n".ToCharArray());
//Now add each row to the DataSet
foreach (string r in rows)
{
//Split the row at the delimiter.
string[] items = r.Split(delimiter.ToCharArray());
//Add the item
result.Tables[TableName].Rows.Add(items);
}
}
//Return the imported data.
return result;
}
}
}
If there aren't supposed to be any missing entries anywhere in the file (i.e there should always be something between the tabs) then you could use:
string[] columns = s.ReadLine().Split(delimiter.ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
and then check that columns is not an empty array. If it is then read the next line and carry on processing:
while (columns.Length == 0)
{
// Row is empty so read the next line out of the file
columns = s.ReadLine().Split(delimiter.ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
}
This will ensure that your data always starts with a filled row. However, it will break down if there is ever an empty entry further down the list.
If there could be empty entries then you'll probably have to check for all columns being empty:
while (columns.All(c => string.IsNullOrEmpty(c)))
{
// Row is empty so read the next line out of the file
columns = s.ReadLine().Split(delimiter.ToCharArray());
}

how to check each elements of string array contains data or not in c#

i have created web application and using textbox and it can contains multiple line of data becoz i have set its textmode property is multiline.
my problem is that i want to check each line contain data or not so i using count variable which count how many line contain data.
string[] data;
int cntindex;
data = txt_invoicenumber.Text.ToString().Split("\n".ToCharArray());
cntindex = data.Length;
for (j = 0; j < cntindex; j++)
{
if (data[j]!="")
{
inv_count++;
}
}
Its not working.
Please help me.
I guess this is because new line is \r\n so there is a '\r' also on empty lines.
Change the if statement to:
if (data[j].Trim().Length != 0)
Firstly, You don't need to ToString() the .Text property as it is already a string.
try this
string[] lines = txt_invoicenumber.Text.Split(Environment.NewLine);
int lineCount = 0;
foreach(string line in lines)
{
if(!string.IsNullOrEmpty(line))
{
lineCount ++;
this.ProcessLine(line);
}
}
var lb = new String[] { "\r\n" };
var lines = txt_invoicenumber.Text.Split(lb, StringSplitOptions.None).Length;
This will count empty lines too. If you don't want to count empty lines, use the StringSplitOptions.RemoveEmptyEntries value.
Don't count 100% on "\r\n" if you have little control over your environment though.
This is the answer I came up with.
String[] lines = TextBox1.Text.Split(new Char[] { '\r', '\n' },
StringSplitOptions.RemoveEmptyEntries);
Int32 validLineCount = lines.Length;