Make outline in Excel OpenXML - c#

I'm adding rows to a spreadsheet using OfficeOpenXml row copy method, Every time I add a row, I set the outlinelevel of the row (olLevel incremented outside of loop below). I'm testing with 12 total rows, attempting to place in two groups of six.
for (int j = 0; j < employeeRecordCount; j++) {
detailRow.Copy(outputSheet.Cells[detailRowStart + j, columnA]);
outputSheet.Row(detailRowStart + j).OutlineLevel = olLevel;
startingRow++;
lastdetailRow++;}
When I open the spreadsheet, all rows are in one group of 12 and the last six rows are grouped but nested within the larger group (the six collapse/expand independently of all 12). If I repeat 6 of the records from my input file, those records are grouped together as 12 and the other 6 are nested.
I know I'm forgetting to set something besides outlinelevel to keep the groups seperate from each other but I cannot figure it out.
Can anyone see what I am missing?

The issue was that every detail row began with a header row. Excel was grouping all the rows on one level and creating another nested level to group rows under the next unique header row.
I edited the code to not apply an outline level to the first detail record (header row) and the rows are no longer nested.

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.

Excel - ClosedXML - Best way to get visible rows following applying SetAutoFilter/AddFilter?

Using this example, https://github.com/ClosedXML/ClosedXML/blob/develop/ClosedXML_Examples/AutoFilters/RegularAutoFilter.cs
ws.RangeUsed().SetAutoFilter.Column(1).AddFilter("123");
ws.RangeUsed().SetAutoFilter.Column(2).AddFilter("abc");
I'm successfully filtering a table by multiple columns. Let's say it has 20 rows, and applying the filter reduces the visible rows to 2 (rows 7 & 12).
Great, the filter works, but how can I quickly get the visible rows?
Right now, I'm having to loop through the entire range used to find the rows that are visible, hence match the filter.
var visibleRows = ws.RangeUsed().Rows(r => !r.WorksheetRow().IsHidden);

Adding rows to second column ONLY - populating data using a for loop

I calculate the amount of rows I want to have in my second column using a for loop based on reading how many records a file has that has been opened. I have researched and tried various solutions but nothing works, yet it seems so simple. Below is my current code where I retrieve the file's length and do a quick sum, entering a for loop where (at the moment) I am only able to populate the first column.
long Count = 1;
FileInfo Fi = new FileInfo(file);
long sum = (Fi.Length / 1024) - Count;
for (int i = 0; i < sum; i++)
{
DataGridView1.Rows.Add(Count++);
}
I'm not sure how to do it but I know the above code adds to the first column by default - I don't know how to modify it. I know by:
DataGridView1.Rows.Add("a","b");
... The 'b' value is displayed in the second column, but I don't want anything for now in the first where 'a' is.
I have looked at insert a row with one column datagridview c# but it is related to merging columns, again, I don't want this.
DataGridView1.Rows.Add("",Count++);
Works to an extent, but is not the right way to do it. I'm going to be adding data to the first column later on.
If you want to omit the value for the first column, just add null or DBNull.Value, e.g.:
DataGridView1.Rows.Add(DBNull.Value, Count++);
This way, the first column will be empty while the second columns contains the value of Count.

C# 2010 Word - How to create tables without an empty line between

Using C# 2010 I need to open a word 2010 template, search for a bookmark and insert a table there. Actually it should be a 'three-part-table': one row with two columns, after that multiple rows with five columns and finall three rows as single columns. And it should look as one table without paragraphs or empty lines between.
My experience with word automation is quite limited. I can find examples how to create a table at a bookmark - no problem so far - but how can I add a new table immediately after the one before...
Thanks a lot for any help!!
This should do the trick. You don't need multiple tables in order to have different columns; Word lets you have a single table where the first row has 2 columns, the next 3 rows have 5 columns, and the last 3 rows only have 1 column. (You didn't say how many rows you needed with five columns, so I just went with 3.)
//Be sure to add this reference:
//Project>Add Reference>.NET tab>Microsoft.Office.Interop.Word
//open Word App
Microsoft.Office.Interop.Word.Application msWord = new Microsoft.Office.Interop.Word.Application();
//make it visible or it'll stay running in the background
msWord.Visible = true;
//open a new document based on the Word template.
//You shouldn't open the template directly using msWord.Documents.Open(path) unless you want to edit the template itself.
Microsoft.Office.Interop.Word.Document wordDoc = msWord.Documents.Add(#"c:\MyTemplate.dotx");
//find the bookmark
string bookmarkName = "BookmarkToFind";
if (wordDoc.Bookmarks.Exists(bookmarkName))
{
Microsoft.Office.Interop.Word.Bookmark bk = wordDoc.Bookmarks[bookmarkName];
//set the document's range to immediately after the bookmark.
//If you want to add the table *into* the bookmark, it needs to be done differently.
//This page has a good explanation of the differences between adding to the bookmark's range vs adding after the bookmark's range.
//http://gregmaxey.mvps.org/word_tip_pages/insert_text_at_or_in_bookmark.html
//It's a little more hassle because you have to re-add the bookmark after inserting into it,
//so inserting after the bookmark is usually fine less you're going to be inserting text programmatically at the same bookmark a second time.
Microsoft.Office.Interop.Word.Range rng = wordDoc.Range(bk.Range.End, bk.Range.End);
//create a table with 8 rows and 5 columns into the range.
Microsoft.Office.Interop.Word.Table tbl = wordDoc.Tables.Add(rng, 8, 5);
//set the table's borders.
tbl.Borders.InsideLineStyle = Microsoft.Office.Interop.Word.WdLineStyle.wdLineStyleSingle;
tbl.Borders.OutsideLineStyle = Microsoft.Office.Interop.Word.WdLineStyle.wdLineStyleSingle;
//merge the cells in the first row down to 2 columns (Word's cells start at 1, not at 0).
tbl.Cell(1, 1).Merge(tbl.Cell(1, 3));
//distribute the columns evenly
tbl.Rows[1].Select();
msWord.Selection.Cells.DistributeWidth();
//rows 2-5 already have 5 columns so don't touch them.
//merge rows 6-8 into single-columns rows.
for (int x = 6; x < 9; x++)
{
tbl.Cell(x,1).Merge(tbl.Cell(x,5));
}
//put the cursor in the table's first cell.
rng=wordDoc.Range(tbl.Cell(1,1).Range.Start, tbl.Cell(1,1).Range.Start);
rng.Select();

Delete multiple rows from Grid

How do I delete multiple rows from XtraGrid ? I am using DevEx version 10.2. Any tutorials available ?
You can get the selected rows using the GetSelectedRows method (nicely named right?).
Then you can just use a loop to go through the rows and delete the ones selected.
Also, I found this "tutorial" which might be what you are looking for: http://www.devexpress.com/Support/Center/KB/p/A234.aspx
It talks about the ColumnView.DeleteSelectedRows method, though it's only available in newer versions of XtraGrid.
you can't delete more than one row at time but we can Trick on the c#.
actually when you delete one row from the gridview by using this statement GridData.Rows.RemoveAt(RowIndex);
the rows count is decremented by one and the row index will change so you must be careful about that.
here you are, first you can create an integer variable which equal zero and when you remove one row increment it by one.
second, put the index of the rows you want to delete in an array and then use for loop to delete the rows but again take care when you send your parameter.
int deletedValue = 0 ;
for (int j = 0; j < counter; j++)
{
if (Array.binarySearch(myArray,j)){
GridData.Rows.RemoveAt(j-deletedValue); deletedValue++;`
}
else {//The non deleted rows}}
}

Categories

Resources