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);)
Related
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 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!
I need to take values form one sheet in one Excel workbook and insert them into another existing workbook.
The values I need to take are the first 6 columns of the first file:
And I want to insert them at the beginning of another book like so
I've been using Spire.Xls to read values from the first sheet and I thought I could just do the same; parse the worksheet, read the values and just paste them into the other sheet, but that wouldn't work because three of the columns I want to copy have the same header "Descripcion" so my parser would only take the values form the first descripcion column and skip the other ones.
Is there any way, using Excel.Interop or maybe Spire itself to copy and paste entire columns between workbooks? Or alternately, is there any way to get all of the 3 "descripcion" values (without rewriting the title of the columns)?
VSTO might be helpful. I've done similar tasks in C#/VSTO.
Perhaps read through: Simple Example of VSTO Excel using a worksheet as a datasource
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.
i have a data file(csv) consisting of 2 columns & 1000 rows, as i load it to my datagridview it takes alot of time, i just want to show only the first 6 rows just as a preview of file to user. Is there any way i can show only the first 6 rows in my datagrid view. Following is the code im displaying the data in DataGridView.
DataTable csvDataTable = CSVReader.ReadCSVFile(textBoxCsv.Text, true);
dataGridViewCsvData.DataSource = csvDataTable;
dataGridViewCsvData.SelectionMode = DataGridViewSelectionMode.FullColumnSelect;
CSVReader is an open source project isn't it? try to add ReadTopLines method to that class that will read only top N lines given as parameter
Every datatable has it's own DefaultView.
http://msdn.microsoft.com/en-us/library/system.data.datatable.defaultview.aspx
You can then get the Table from the view by DefaultView.GetTable. And you can manipulate data in you View the way you want. You can filter up, query.
You can find out more about expressions here:
http://msdn.microsoft.com/en-us/library/system.data.datacolumn.expression.aspx
OR, since CSVReader is an open-source project, you can simply change
public DataTable CreateDataTable(bool headerRow)
Add number of lines to this method, and you will get what you need without reading the whole file.
I didn't read the whole source, so there might be a solution without even changing a code.
Use Open Source for 100%. Change it, customize it, send you patches! People do appreciate it! And you will get experience, knowledge and new friends who might help you in future :)