Join string to 2d array, which already contains string or null - c#

I would like to create code, to join few text files (each one has different structure) into one with unifying build.
For now, I manage to open all files, split strings in rows by tabulator and save everything into one two dimensional lists.
Example of current data:
809187.49 226885.80 26934
809183.14 226877.21 26937a
2 5509514.58 6558911.86 0.00 80T
3 5509515.55 6558913.48 0.00 80T
4 5509516.35 6558914.56 0.00 80T
Next, I am going to reprint content from a two-dimensional list into a new array (with n rows and 2 columns) and sort all data at the same time. All double type, greater then 100000.00 I want to put into the second column with ',' separator and the rest of content of each row from the list I would like to put into the first column:
Result:
26934 809187.49,226885.80
26937a 809183.14,226877.21
2,0.00,80T 5509514.58,6558911.86
3,0.00,80T 5509515.55,6558913.48
4,0.00,80T 5509516.35,6558914.56
And here is the problem. I used code like below:
string[,] resultArray = new string[RowNo, 2]; //Create Array
for (int i = 0; i < resultList.Count; i++)
{
for (int j = 0; j < Regex.Matches(file[i], " ").Count+1; j++)
{
if (double.TryParse(resultList[i][j], out n)) // record is a double type greater then n
{
if((Double.Parse(resultList[i][j]) % 1) > 0) // record is not a int type
{
if (resultArray[i, 1] != null) // if cell in array is not null
{
resultArray[i, 1].Insert(resultArray[i, 1].Count(), "," + resultList[i][j].ToString()); // add content of List in to string in second column
}
else // if cell in array is null for now
{
resultArray[i, 1].Insert(0, "," + resultList[i][j].ToString()); // put content of List in to second column
}
}
if (resultArray[i, 0] != null) //if cell in array is not null
{
resultArray[i, 0].Insert(resultArray[i, 0].Count(), ";" + resultList[i][j].ToString()); // put content of List in to first column
}
else // if cell in array is null for now
{
resultArray[i, 0].Insert(0, "," + resultList[i][j].ToString()); // put content of List in to first column
}
}
else
{
if (resultArray[i, 0] != null) //if cell in array is not null
{
resultArray[i, 0].Insert(resultArray[i, 0].Count(), ";" + resultList[i][j].ToString()); // put content of List in to first column
}
else // if cell in array is null for now
{
resultArray[i, 0].Insert(0, "," + resultList[i][j].ToString()); // put content of List in to first column
}
}
}
}
But unfortunately, when I run code I receive bug "Object reference not set to an instance of an object"
I have make some research and try something like this:
resultArray[i, 1] += resultArray[i, 1] + "," + res_file[i][j].ToString();
instead
resultArray[i, 1].Insert(resultArray[i, 1].Count(), "," + res_file[i][j].ToString());
But it wasn't work correctly. I received some results but data in record was duplicated.
I will appreciate every help.

The problem is with all your else conditions:
You are doing
if (resultArray[i, 0] != null) //if cell in array is not null
{
resultArray[i, 0].Insert(resultArray[i, 0].Count(), ";" + resultList[i][j].ToString()); // put content of List in to first column
}
else // if cell in array is null for now
{
resultArray[i, 0].Insert(0, "," + resultList[i][j].ToString()); // put content of List in to first column
}
which basically means do if block when resultArray[i, 0] != null, but in the else block you are trying to access the Insert() method of that null object. Hence the error. All of your else blocks are like that.
I think what you want to do is an assignment in your else blocks (which you seem to have figured out)... like:
resultArray[i, 0] += "," + resultList[i][j].ToString());
The problem with duplicates may have been that you are using both += and the left hand side (LHS) expression in
resultArray[i, 1] += resultArray[i, 1] + "," + res_file[i][j].ToString();
When you do x += 1; it is same as x = x + 1;
You are doing: x += x + 1; which is same as x = x + (x + 1);

Related

How to skip empty cells while reading data from Excel using OpenXML?

I am trying to read data from Excel and store it into a DataTable using OpenXML. I want data in my DataTable as it is in Excel sheet but when there is a empty cell in Excel, it was not looking as expected.
Because code row.Descendants<Cell>().ElementAt(i) skips empty cells while reading data and in DataTable Rows and Columns are stored incorrectly. I resolved this issue using below code but when my excel has more than 26 columns, it is not working as expected and again data are stored in DataTable incorrectly.
(i.e., While reading data from AA, AB, AC columns)
Can someone help me to rewrite this code to handle this issue when there is more than 26 columns.
private static int CellReferenceToIndex(Cell cell)
{
int index = 0;
string reference = cell.CellReference.ToString().ToUpper();
foreach (char ch in reference)
{
if (Char.IsLetter(ch))
{
int value = (int)ch - (int)'A';
index = (index == 0) ? value : ((index + 1) * 26) + value;
}
else
{
return index;
}
}
return index;
}
You can use example below (taken from here and improved by few validations):
public static int GetColumnIndex(this Cell cell)
{
string columnName = string.Empty;
if (cell != null)
{
string cellReference = cell.CellReference?.ToString();
if (!string.IsNullOrEmpty(cellReference))
// Using `Regex` to "pull out" only letters from cell reference
// (leave only "AB" column name from "AB123" cell reference)
columnName = Regex.Match(cellReference, #"[A-Z]{1,3}").Value;
}
// Column name validations (not null, not empty and contains only UPPERCASED letters)
// *uppercasing may be done manually with columnName.ToUpper()
if (string.IsNullOrEmpty(columnName))
throw new ArgumentException("Column name was not defined.", nameof(columnName));
else if (!Regex.IsMatch(columnName, #"^[A-Z]{1,3}$"))
throw new ArgumentException("Column name is not valid.", nameof(columnName));
int index = 0;
int pow = 1;
// A - 1 iteration, AA - 2 iterations, AAA - 3 iterations.
// On each iteration pow value multiplies by 26
// Letter number (in alphabet) + 1 multiplied by pow value
for (int i = columnName.Length - 1; i >= 0; i--)
{
index += (columnName[i] - 'A' + 1) * pow;
pow *= 26;
}
// Index couldn't be greater than 16384
if (index >= 16384)
throw new IndexOutOfRangeException("Index of provided column name (" + index + ") exceeds max range (16384).");
return index;
}
All exception throws you can replace with return -1 and some kind of Log("...") if you have logging. Otherwise you may not be sure what's problem happened and why was returned -1.
Usage is obvious:
var cells = row.Descendants<Cell>();
foreach (Cell cell in cells)
{
int columnIndex = cell.GetColumnIndex();
// Do what you want with that
}
EDIT.
I'm not sure what you're trying to achieve. And what you mean here:
Because code row.Descendants<Cell>().ElementAt(i) skips empty cells...
I didn't see that. Look at example below:
Random ElementAt in range between 0 and Descendants<Cell>().Count() works too and shows both empty and non-empty cells:

Odd System.IndexOutOfRangeException when trying to overwrite .txt file c#

I want to extend a data collection in a .txt file.
I'm reading a .txt file into a string array. Then I'm making a new string array with 5 more elements.
string oldarray[] = File.ReadAllLines(targetfile); //it is correctly reading the file
string newarray[] = new string[oldarray.Count()+5];
for (int i = 0; i < oldarray.Count(); i++) { //copy old array into new bigger one
newarray[i] = oldarray[i];
}
newarray[oldarray.Count() + 1] = "Data1"; //fill new space with data
newarray[oldarray.Count() + 2] = "Data2";
newarray[oldarray.Count() + 3] = "Data3";
newarray[oldarray.Count() + 4] = "Data4";
newarray[oldarray.Count() + 5] = " "; //spacer
//now write new array into same textfile over old data
File.WriteAllLines(targetfile, newarray); //System.IndexOutOfRangeException
I also tried writing line by line to the file like so, but it did just spit out the same exception:
using (StreamWriter writer = new StreamWriter(destinationFile)) //System.IndexOutOfRangeException
{
for (int i = 0; i < newarray.Length; i++)
{
writer.WriteLine(newarray[i]);
}
}
Why does it do that, and how do I fix it?
You're off by one - the last element in olaArray is at oldarray.Count() - 1, not oldarray.Count()
for (int i = 0; i < oldarray.Count(); i++){ //copy old array into new bigger one
newarray[i] = oldarray[i];
}
newarray[oldarray.Count()] = "Data1"; //fill new space with data
newarray[oldarray.Count() + 1] = "Data2";
newarray[oldarray.Count() + 2] = "Data3";
newarray[oldarray.Count() + 3] = "Data4";
newarray[oldarray.Count() + 4] = " "; //spacer
Array indexes are zero-based so oldarray.Count() + 5 points to an element after the end of the array. The first element is left empty too.
This could be fixed by fixing the indexes to be between 0 and 4 instead of 1 and 5. A better solution though would be to load the lines as a list and append the new strings :
string lines = File.ReadLines(targetfile).ToList();
var newLines=new[] {"Data1","Data2"...};
lines(newLines);
File.WriteAllLines(targetfile, lines);
Or even
var newLines=....;
string lines = File.ReadLines(targetfile)
.Concat(newLines)
.ToList();
File.WriteAllLines(targetfile, lines);
ReadAllLines uses a List as well and returns a copy of the list as an array. ReadLines on the other hand, returns lines one at a time as an IEnumerable<string>. The file remains open as long as the IEnumerable is iterated, so we need ToList() to consume it and allow the file to close before overwriting it.
The index oldarray.Count() + 5 does not exist in your new array.
Array indexing starts from zero. If you have an array with 10 elements then the first index is 0 and the last index is 9. If you make a new array with oldarray.Count() + 5 items it'll have 15 items and the last index will be 14 (not oldArray.Count + 5 which equals 15).
Just do like this:
newarray[oldarray.Count()] = "Data1";
newarray[oldarray.Count() + 1] = "Data2";
newarray[oldarray.Count() + 2] = "Data3";
newarray[oldarray.Count() + 3] = "Data4";
newarray[oldarray.Count() + 4] = " ";

Searching for a string in a part of a multidimensional array c#

I need to find the location of a string in a part of a multidimensional array.
If you have:
string[,] exampleArray = new string[3,y]
Where 3 is the number of columns and y is the number of rows, I need to find the location of a string in the full y row but only in the second or third 'column'. So I want my program to search for the location of the string in [1,y] and [2,y].
One possible solution is to iterate your rows and check each column of index 1 and 2 on each row.
//Example array to search
string[,] exampleArray = new string[y,3]
//string to search for
string searchedString = "someValue";
//for-loop to iterate the rows, GetLength() will return the length at position 0 or (y)
for(int x = 0; x < exampleArray.GetLength(0); x++)
{
if(string.Equals(exampleArray[x, 1], searchedString))
{
//Do something
Console.Writeline("Value found at coordinates: " + x.ToString() + ", " + 1.ToString());
}
if(string.Equals(exampleArray[x, 2], searchedString))
{
//Do something
Console.Writeline("Value found at coordinates: " + x.ToString() + ", " + 2.ToString());
}
}

adding element in a list throws ArgumentOutOfRangeException

My code throws this:
ArgumentOutOfRangeException: Argument is out of range.
Parameter name: index error
When it finds an element in a list that have a count less that a specific number. any ideas on how to correct the code?
I've added debug.log code everywhere to determine exactly where the error happens, because no error is underlined by Visual Studio.
List<int> emptyRows = new List<int>();
for (int j = 0; j < gridPositions.Count; j++) // try to find if a row is still empty
{
Debug.Log("gridPositions[" + j + "].Count is " + gridPositions[j].Count);
Debug.Log("columns are" + columns);
if (gridPositions[j].Count == columns)
{
Debug.Log("trying to add to emptyrows");
emptyRows.Add(j);
Debug.Log("added to emptyrows and its count is " + emptyRows.Count);
}
else
{
Debug.Log("found an occupied row at row " + j);
//ERROR STRIKES HERE
}
Debug.Log("emptyRows is " + emptyRows[j]);
Debug.Log("emptyRows count is " + emptyRows.Count);
}
I expect the emptyRows to track and record all unoccupied rows, but when it fills an occupied row, it not proceeds whit the for loop and stops.
You are only adding to emptyRows if (gridPositions[j].Count == columns)
But you are accessing the emptyRows[j] on every value of j
So the emptyRows ends up having less items then the value of j is

Populate an array element with 2 datarows at a time

i want to populate an array element with 2 datarows at a time.
i am using javascript pausescroller and on every single array element i want to show 2 Rows in the scroller.
sample code is
Datatable tblNews;
for(int i = 0; i < tblNew.Rows.Count; i++)
{
array[i] = tblNews.Rows[i][""].ToString() + "" + tblNews.Rows[i + 1][""].ToString();
}
but problem is i am getting error that no row found at position 1;
Any solution guys
Yah, quite simply, when you're getting to the end of your tblNew.Rows.Count you're adding another one and that doesn't exist in your rows...
so a quick and dirty fix...
for(int i = 0; i < tblNew.Rows.Count-1; i++)
{
// do a quick check to make sure there is a row there to get data from
string addMe = i + 1 <= tblNews.Rows.Count-1 ? tblNews.Rows[i+1][""].ToString() : "";
array[i] = tblNews.Rows[i][""].ToString() + "" + addMe;
}

Categories