C# datatable take rows one at a time - c#

I have a datatable containing certain columns. I am able to display them in a repeater as a whole. However, what I want to do is to display the row, one by one. I want to create like a go next and show previous button. I did something like the following:
myDataTable.Rows.Cast<DataRow>().Take(1).CopyToDataTable();
This is giving me the first row. Now how can I use this concept to get the next row, (row 2), then row 3..... till row n. The rows being returned are different for different cases. It is an web application.

To get a different row, you just need to Skip some:
myDataTable.Rows.Cast<DataRow>().Skip(n).Take(1).CopyToDataTable();
where n is how many rows you want to skip. So, for the second record n would be 1.
I greatly disagree with the use of CopyDataDataTable(), but it would require a lot of knowledge of your code base to provide a better approach.

I would select it from the database instead, however, use Skip(n).Take(1):
var row3 = myDataTable.AsEnumerable().Skip(2).Take(1).CopyToDataTable();

Introduce the use of .Skip():
myDataTable.Rows.Cast<DataRow>().Skip(0).Take(1).CopyToDataTable();
Now you can simply track which record the user is currently viewing, and update the value sent to the .Skip() method. For example, if the user has pressed "next" 5 times, you've incremented the value 5 times:
myDataTable.Rows.Cast<DataRow>().Skip(5).Take(1).CopyToDataTable();

Keep a counter and use Skip(n-1).Take(1) for nth record.

Related

SSIS need to add same rownumber to rows, then reset when it finds a certain value in a row, from file source

I have a file source where the data is not in normalized form with any sort of primary key value or repeating group value. I am using Merge Join to put the multiple rows into one merged row. I need to apply some row numbering so that I have a join between the multiple rows, to get them into the one single row for the merge join.
Here is what the source data looks like:
Data Rows:
MSH|BLAH|||BLAHBLAH15|BLAHZ|||
EVN|MOREBLAH|BLAHBLAH11|BLAHY|||
PID|BLAHXX|BLAHBLAH655|BLAHX|||
PV1|BLAHX2|BLAHBLAH42|BLAHX|||||||||
DG1|1||84|XXXX||A
IN1|1||11400|TEST
IN1|2||20100|TEST2
MSH|BLAH2|BLAHBLAH5|BLAHZ|||
EVN|BLAH6|20220131123100
PID|BLAHGG|BLAH222|BLAHX|||
PV1|PV1|BLAHX2|BLAHBLAH42|BLAHX||||||||20220101|
DG1|1||84|XXXX||A
DG1|2||84|XXXX||A
IN1|1||11600|TEST2
What is consistent is that there is always an MSH line as the header, and everything below it belongs with the MSH line at the top.
So I'm trying to accomplish this by applying a row numbering as below, where it goes from 1,1,1,1 to 2,2,2,2,2 incrementing by one wherever it finds the MSH line, as per below:
Data Rows: Numbering Needed:
MSH|BLAH|||BLAHBLAH15|BLAHZ||| 1
EVN|MOREBLAH|BLAHBLAH11|BLAHY||| 1
PID|BLAHXX|BLAHBLAH655|BLAHX||| 1
PV1|BLAHX2|BLAHBLAH42|BLAHX||||||||| 1
DG1|1||84|XXXX||A 1
IN1|1||11400|TEST 1
IN1|2||20100|TEST2 1
MSH|BLAH2|BLAHBLAH5|BLAHZ||| 2
EVN|BLAH6|20220131123100 2
PV1|PV1|BLAHX2|BLAHBLAH42|BLAHX|||||| 2
DG1|1||84|XXXX||A 2
DG1|2||84|XXXX||A 2
IN1|1||11600|TEST2 2
I can't use a specific row count to reset the number, ie: Every 5 rows increment the row numbering, because it's an inconsistent number of rows each time. In the example above, the first set is 7 rows and the 2nd set is 6 rows. I have to do my incrementing by the presence of the "MSH" row value, and apply the same number on down until it finds the next "MSH". I know that have to use a script task (preferably in C#) to generate this row number since my source is a file. But I just can't seem to find the right logic that will do this, since my data doesn't have a repeating key for each row that I can partition by.
This is what I would do to meet your requirements:
Read entire row in a flat file viewer
Go into a script task (source). I forgot to mention to add the row as read only.
Set up an output for each type.
Go into the code.
Set up a variable outside of main processing (in startup)
int counter = 0;
In main row processing:
string[] details = Row.Split('|');
switch(details[0])
{
case "MSH":
counter++; //increment counter
OutputBufferMSH.AddRow();
OutputBufferMSH.Counter = counter;
OutputBufferMSH.Col1 = details[1];
// Repeat for each detail Column
break;
case "EVN":
OutputBufferEVN.AddRow();
OutputBufferEVN.Counter = counter;
OutputBufferEVN.Col1 = details[1];
// Repeat for each detail Column
break;
//Repeat for each row type
}
I personally would not use this counter approach but actually load the MSH row and return the identity column to replace the counter.
Honestly, I would do the whole thing in a console application instead and use a StreamReader to load the flatfile. Readlines and then use the above logic to push the data into DataTables and use a Bulk Insert to load the data. But the above is the solution to do this in SSIS.
There is a lot to unpack here if you are not familiar with C# or the script task object itself.

ListObject.Resize() makes DataBodyRange null when row count == 1

I am trying to reset the number of columns in an Excel ListObject. I know you can add and remove columns one-by-one, but I want to avoid unnecessary loops. I instead decided to resize the ListObject using the Resize method.
Here is the code that I am using (where OutputCasesTable is the ListObject):
OutputCasesTable.DataBodyRange.Value2 = "";
OutputCasesTable.Resize(OutputCasesTable.Range.Resize[ColumnSize: CaseCount]);
OutputCasesTable.DataBodyRange.Value2 = OutputCasesAray;
The above lines of code appear to work perfectly, however if the ListObject only contains 1 row of data, the DataBodyRange of the ListObject becomes null on the second line - producing an error when I try to change its cell's value. The row in excel still appears to be present.
The MSDN documentation says the following:
"The header must remain in the same row and the resulting list must overlap the original list. The list must contain a header row and at least one row of data."
Now I understand that "one row of data" implies that the row contains values - so the cause of the error here must be that the DataBodyRange cells all contain no value (""). However, a table with two data rows containing "" still doesn't have a row with data, does it?
I know there are many ways of accomplishing this task, but I want to understand why this happens.
Temporary Solution:
Replaced the code to only set the values to empty strings in columns that will be removed (columns above the new column count). All other columns will be replaced:
if(OutputCasesTable.ListColumns.Count - CaseCount > 0)
OutputCasesTable.DataBodyRange.Offset[ColumnOffset: CaseCount].Resize[ColumnSize: OutputCasesTable.ListColumns.Count - CaseCount].Value2 = "";
OutputCasesTable.Resize(OutputCasesTable.Range.Resize[ColumnSize: CaseCount]);
OutputCasesTable.DataBodyRange.Value2 = OutputCasesAray;
Personally I prefer looking at the first solution!
Is there anything I can do make it work with empty strings? Or do you have a better solution?
Best regards,
The Resize operation is the piece that kills the DataBodyRange, and clearly there's some internal logic that Resize uses, along the lines of "if there is only one row, and all the cells are empty, remove all the data rows. If there is more than one row, don't remove any".
I agree that this logic is a bit confounding. If your question is why did Microsoft implement it this way, I'd argue that although it's inconsistent, it's perhaps tidier in a way - it appears to the model that you're working with an empty table, and there's no way for the model to tell the difference graphically (it's not possible for a table to just have a header row).
When Resize turns up to do its work and finds a single-row blank table, it can't tell whether you have a zero-row table or a single-row table with empty strings. If it arrives and finds two empty rows, that's unambiguous (they must be meaningful rows).
For the workaround portion of your question, I'd suggest a tidier solution of just checking the ListRows.Count property, and adding one if necessary. Note that you can also use Clear instead of setting Value2 to blank; for me it reads as more self-explanatory.
OutputCasesTable.DataBodyRange.Clear();
OutputCasesTable.Resize(OutputCasesTable.Range.Resize[ColumnSize: CaseCount]);
if (OutputCasesTable.ListRows.Count == 0) OutputCasesTable.ListRows.Add();
OutputCasesTable.DataBodyRange.Value2 = OutputCasesAray;

DataGridView to show calculated values from 3 other datagridview

I really need some help in this one
I have 3 tables - First one is tblReceive with columns size1R , size2R, .... ,size9R
second one is tblDispatch with columns size1D, size2D,.... , size9D
and third one is tblBroken with columns size1B, size2B, .... size9B
now i want a dataGridView to show size1, size2, .... size9 but the values should be size1R - size1D - size1B , size2R - size2D - size2B and so on.
I want to know the best practice to perform such task
I have 3 dataGridView in my form. one to add data to tblReceive and second to add data to tblDispatch and third to add data to tblBroken. How do I get the data from each table and put it in a variables so that i can do the calculation
Thanks Heaps
Have you heard about: SelectedValue,SelectedValuePath and DisplayMemberPath ? They might give you a nudge in the right direction. (Fair disclosure: I wrote that article :).
Another option would be to weave some linq to get the objects you want, but you'll have to provide an example of what you have and what you expect in order to get more help.

Little Confused about the Microsoft Excel Interop Library

I know how to make new columns, I know how to add a header to that column, but I am a little unsure about adding values programatically.
I am going to be looping through rows and then adding values to the new columns that I create based on some functions I perform on the Data Set. I thought a good way to start would be to just pick a row and loop through it and print out all the information in that row. If I could figure out how to do that, I could probably right all the code necessary to loop through appropriate rows and get the data I need. But I am a little confused about how to use this Range object...
Range rng = (Range)wkSheet.get_Range("A1", Type.Missing);
Lets say I wanted to print out all the Range Row information to a console? How would I loop through that Range and print out that information? Even change the information in the Range. I know how to change the value of a single row, the header, but changing multiple rows is alluding me.
object[,] values = (object[,])rng.Value;
Probably duplicate reading-from-excel

Need to display data as it is returned using web service/jquery

I have an operation (That I can't change) that starts threads that make calls to our Oracle database to see if a certain hotel(s) has availability on a certain date.
If a date/hotel combination has availability, that thread returns information about the date/hotel in the form of a DataTable that is merged into a Main DataTable of results. Yes, I know ... I inherited this.
So I am trying to re-write this operation. I still must query Oracle in threads to get the availability information, but I want to display the data as it is returned (in chunks of 5, 10? I'm flexible), instead of having the user sit in front of the screen for up to 4 minutes before a complete result is spat out into a GridView.
How do I do this directly from an .aspx page so I can make a web service call and populate a grid (JqGrid?) with the results?
If I haven't provided enough information or described what I am trying to achieve, please let me know and I will elaborate.
Oracle provides a field on each row called "rowid"
(http://www.adp-gmbh.ch/ora/concepts/rowid.html)
The first time you send the query, send in the int (x) to define what the highest rownumber you want is. Have the service return the total number of rows and the first x rows.
Then, the 2nd time you send the query, get the next x rows, rinse and repeat.
Basically, you need to send an ajax query for rows x through y each time until you have them all loaded.
I would recommend paging as well, since users typically don't want to see hundreds of results at a time.

Categories

Resources