I have a table in an Excel worksheet where I need to programatically remove entire rows using VSTO. After a lot of searching here and everywhere else, I was unable to find the answer. Due to some unrelated code, I also cannot delete the first row of the table, but need to remove all other rows.
Here are the specific requirements:
One of the functions of this addin is to populate the table. This is done through a loop starting with the "root" named range in the left column of the first row of the table.
Whenever populating the table, I first need to delete all data from the table and then add the new data. I need to use the "root" to add the data, so I can't have it deleted.
I am using the Table for the automated formatting instead of formatting the table manually after adding each cell.
I never know how many rows will be added, but it will always be at least one.
After banging my head on this for a few hours, I slept on it and came at it refreshed this morning. After much trial and error, here is the code I came up with.
var deplTable = ThisSheet.Evaluate("DeploymentTable");
if (deplTable.ListObject.ListRows.Count > 1)
{
do deplTable.ListObject.ListRows[2].Delete();
while (deplTable.ListObject.ListRows.Count > 1);
}
NOTE: ThisSheet is set to the correct sheet earlier. The application works on multiple sheets, so it needs to be flexible.
I tried this a few ways before finally getting it to work. Looping through the rows gave unexpected results; possibly due to timing issues between Excel and VSTO.
Hope this helps other people!
Related
This seems like it should be simple, but I am not finding a good answer.
I have a DataGridView that is populated from a DataTable. I want the user to be able to export it in Excel. However, the dgv has 20 columns and in my export, I just want to copy the first 5 columns.
I would imagine something like this dgv.Columns[0, 4].Select(); should work, but it does not.
So far, I have just done dgv.SelectAll(); and copied that to the clipboard, then dumped the whole thing in Excel, finally deleting columns 6-20. It just feels inelegant, and I figure there has to be a better answer.
Sure, use something like EPPlus to generate an excel file directly. It can load from a datatable
using var p = new ExcelPackage(...);
var ws = pck.Workbook.Worksheets.Add("...");
ws.Cells["A1"].LoadFromDataTable(dt, true);
p.Save();
Simplest way to dump everything except the first 5 columns would probably be to Copy() it (or modify the original if you're done with it) and jettison the 6+ index columns (while(dt.Columns.Count>5) dt.Columns.RemoveAt(5);)
I have a tool I made for work. Every week there are 5-20 files for a certain process that fails and I have to find their job ids and rerun them.
I made a tool in C# that takes the names of the failed files in an Excel spreadsheet (we'll call it the Failed File Spreadsheet, or FFS if you're feeling cynical) and then cross references them with a different Excel spreadsheet that has the job ids, and displays the result in the terminal. It reads the FFS this with a fairly simple OledDbDataAdapter code:
public static DataTable GetDataFromExcel(string filename, string sheetName)
{
using(var oledb = new OleDbConnection(CONN_STR.Replace("<FILENAME>", filename).Replace("<HDR>", "no"))
{
var result = new DataSet();
new OleDbDataAdapter($"SELECT * FROM [{sheetName}]", oledb).Fill(result);
return result.Tables[0];
}
}
The tool works fine, mostly. It cross references with another excel sheet and I get my job ids and I can carry on with my task.
However there's one slight issue, and that is that, often when running the tool, when it reads from the FFS, sometimes it returns blank lines. Like if last week I had 7 files, then this week I erased those, pasted in 5 files, then my tool will show the job ids for those 5 files just fine, but also show two blanks, as if it's still reading those two extra rows from the previous week. If however I make a new blank spreadsheet in Excel, plug in my failed files and overwrite the save file, I don't have this issue at all, making me think this is an Excel issue and not a C# coding issue.
Is there a reason why, if I delete the contents of a cell, the OleDbDataAdapter would still be reading those cells? Like are there whitespace characters or other hidden characters still present after deleting contents? I mean I could fix it in the code and just say "don't write it out if the values are whitespace or null" but I want to know why blank cells are even being read at all.
This is just a minor bug and it's not stopping me from doing my work and this tool is nothing more than a personal tool to help with a weekly task. But I'd still like to know why cells that had content, but then had that content deleted, are still being read.
Excel is a little bit quirky like that. If you are manually editing your "Failed File Spreadsheet" (FFS) and as you say, you are pasting 5 rows over the existing 7 rows, then you may still read in those extra rows after the data you expect, if there is any formatting on the cells. To avoid this, in Excel select the range of cells of the whole sheet and right-click and select "Clear Contents".
To be fair, as you alluded to, I think it would be simpler just to fix it in code and skip rows in the DataTable that are empty. Or there is a SO post here which shows how to remove empty rows from a DataTable
I'm extracting text out of an MS Word document (.docx). I'm using the DocX C# library for this purpose, which works in general quit well. No, I want to be able to extract tables. The main problem is, that if I'm looping through the paragraphs, I can get whether I'm in a table cell with:
ParentContainer == Cell
but I do not get any information about how many rows and cells. Second possibility which I see is that there is a list with tables as property of the document object. There I can see, how many rows / columns and so on - but I do not know where they are.
Does anyone has an idea how to deal with tables correctly? Any other solution would be appreciated as well :)
I figured it out. The trick is, to check whether each paragraph is followed by a table. This can be done by
...
if (paragraph.FollowingTable != null)
{
tableId = paragraph.FollowingTable.Index;
}
...
The FollowingTable.Index will give you an index to the table, with which you can get all details about the table in the Document.Tables list.
I am sorry if this question has been asked before, i have tried using google but all the answers couldn't help me.
I am a total begginer in using datasets and connecting to database using c#. I have a dataset usersDataset gotten from an access 2007 Database that has two table Administrators and Users. Both tables have two columns UserName and Password. The Administrators Table has a row of data.
Now the problem is that i want to retrive the row in the dataset. I have tried many things but they all throw an Exception.
I have tried
DataRow rows = usersDataset1.Administrators.Rows[0];
MessageBox.Show(rows.ToString());
Also tried
usersDataset data = new usersDataset();
MessageBox.Show(data.Administrators.Rows[0].ToString());
Also tried
MessageBox.Show(usersDataset1.Tables[0].Rows[0].ToString());
All of the following code snippets throw an IndexOutofRangeException with the message There is no Row at Index 0.
Then i tried
MessageBox.Show(usersDataset1.Administrators.Rows.Count.ToString());
It shows '0'.
Pls what did i do wrong and how can i correct it?
EDIT : When i drag the Administrator from the DataSources Windom to the form and i run the Application. The row is displayed.
Your current problem (as evidenced by your last example) is that you have no data in the Administrators table. Perhaps you aren't properly loading your data into your data structure?
On a side note, it's generally better to iterate through the rows in a table unless you will always know exactly how many rows it will contain. For example:
foreach (DataRow row in usersDataset1.Administrators.Rows)
{
//Do stuff here...
}
I am making an add-in and I am trying to format the output which my add-in generates,using Format as table table-styles provided by Excel.
The one which you get on the 'home tab' --> 'Format as Table' button on the ribbon.
I am using following code:
SourceRange.Worksheet.ListObjects.Add(XlListObjectSourceType.xlSrcRange,
SourceRange, System.Type.Missing, xlYesNo, System.Type.Missing).Name =
TableName;
SourceRange.Select();
SourceRange.Worksheet.ListObjects[TableName].TableStyle = TableStyleName;
TableStyleName is any style name like TableStyleMedium17, you get it if you just hover a particular style in Excel.
My problem is that, even if I keep the SourceRange as 10 columns, all the columns right till the end get selected and are considered as one table.
Because of that the table I populate right next to it is also considered as a part of the first table that was generated.Since, both the table have same column names excel automatically changes the column names in all the following tables that are generated.
Also, because I am generating the tables in a loop after 2 tables are generated I get the error :
A table cannot overlap another table.
PS: I am clearly mentioning SourceRange as:
var startCell = (Range)worksheet.Cells[startRow, startCol];
var endCell = (Range)worksheet.Cells[endRow, endCol];
var SourceRange = worksheet.get_Range(startCell, endCell);
Kindly suggest a way out.
We were able to figure out what was happening on our end for this:
on the
xlWorkbook.Worksheets.Add([before],[after], Type.Missing, Type.Missing)
call, we had to flip before and after since we wanted the sheets to move right, not left and then accessed
xlWorkbook.Worksheets[sheetCount]
by increasing sheetcount for however many sheets were being generated.
Having it the other way was creating the worksheet to access a previously assigned table formatfrom the SourceRange.Worksheet.ListObjects[TableName].TableStyle = TableStyleName call.
So, I got around this problem a week after posting this, sorry did not update in the rush of things.
This actually is an in built excel functionality.
You cant help it, the excel application will keep doing this.
So, ultimately wrote my own table styles in c# and applied it to the excel range which is mentioned as SourceRange. Its just like writing CSS.
If you are interested in knowing the details of that comment it on this question itself or you can contact me by email from my profile.