Using C# to replace an existing and now defunct legacy routine in Delphi, I’ve been trying re-develop a routine in C# that worked well in Delphi 7 that will open each of my 30 Excel files, select the last 22 rows in each, copy them, and reinsert them back into their respective files.
For example, I find the last row, August of 2019 has 22 business days so I begin my range 22 rows back from the last row.
Using the Excel file, I want to select the rows that range from A4157 to A4178. Then, I want to take the rows I’ve copied and insert them after row A4156 or before row A4157. I then take a separate list of August dates and write them to each of the lower 22 from A4178 to A4200. July is then complete and rows for August are ready to go.
I retain the last row because additional calculations on other worksheets in the same workbook refer to the last row for data and they will index automatically from A4178 to A4200 doing it this way.
As each entry made during the month, its data are copied down to the last row so the last row is always up to date. Another sheet in the workbook uses up-to-date data in its summary.
So far, I can open the Excel workbook and get the right sheet.
The following does highlight the proper row but I get a runtime error. I’m not sure what that means.
I’ve commented out the “select” line and run the “copy” line with the same result. I’m now into my second week trying to work out this problem. I need an example of a functioning routine if possible. A link to a text on C# - MS interfacing would be a great help.
Excel.Range selectRange = excelWorkSheet.Range[excelWorkSheet.Cells[A4157], excelWorkSheet.Cells[A4178].select;
Excel.Range copyRange = excelWorkSheet.Range[excelWorkSheet.Cells[A4157], excelWorkSheet.Cells[A4178]].select;
Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: 'Cannot implicitly convert type 'bool' to 'Microsoft.Office.Interop.Excel.Range''
I'm not 100% clear on what you want in your final worksheet. But I think you're trying to do something like this.
// In your example startRow = 4157 and lastRow = 4178.
// Get the rows to copy (rows 4157 to 4178 in your example).
Excel.Range copyRange = excelWorkSheet.Rows[startRow + ":" + lastRow];
// Insert enough new rows to fit the rows we're copying.
copyRange.Insert(Excel.XlInsertShiftDirection.xlShiftDown);
// The copied data will be put in the same place (starting at row 4157 in
// your example).
Excel.Range dest = excelWorkSheet.Rows[startRow + ":" + lastRow];
copyRange.Copy(dest);
Take a look at Epplus. https://github.com/JanKallman/EPPlus. It's available as a Nuget package.
There is a tutorial in the Github Wiki and a sample app that exercises many of the features.
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
Currently using Aspose for .NET in a C# WebService.
I am currently having issues getting the correct Total Rows using worksheet.Cells.Rows.Count
It is showing that I have around 230 rows but inside the file, I only have 14 rows.
I am guessing because I reuse my Excel file and deleted some rows by highlighting the rows then pressing the delete key.
When I recreate a brand new Excel file, then copy-paste the 14 values in the new file. The worksheet.Cells.Rows.Count works correctly.
Would this be a bug in the library or am I deleting the values in Excel file wrongly or I am using a wrong count property?
Am I missing something?
TIA
Well, RowCollection/ColumnCollection.Count attribute would give you total number of rows/columns which are initialized, so it won't be always reliable to get total number of data rows/cols. I think you should use Worksheet.Cells.MaxDataRow and Worksheet.Cells.MaxDataColumn properties to get the farthest (last) row/column indices (0 - based), see the sample code segment for your reference:
e.g
Sample code:
Workbook workbook = new Workbook("Book1.xlsx");
//Get the farthest (last) row's index (zero-based) which contains data.
int lastRowIndex = workbook.Worksheets[0].Cells.MaxDataRow;
//Get the farthest (last) column's index (zero-based) which contains data.
int lastColIndex = workbook.Worksheets[0].Cells.MaxDataColumn;
......
Hope, this helps a bit.
PS. I am working as Support developer/ Evangelist at Aspose.
I used this but get wrong column count:
var dataTable = worksheet.Cells.ExportDataTable(0, 0,worksheet.Cells.Rows.Count, worksheet.Cells.Columns.Count, options);
Instead of worksheet.Cells.Rows.Count and worksheet.Cells.Rows.Count use these : worksheet.Cells.MaxRow + 1 and worksheet.Cells.MaxColumn + 1
This works correctly :
var dataTable = worksheet.Cells.ExportDataTable(0, 0, worksheet.Cells.MaxRow + 1, worksheet.Cells.MaxColumn + 1, options);
I have an excel daily program like this:
I can read excel cells in specific rows or cols. But I want to understand, A,B,C,U,M,S values are Sunday values and C,K,M,S,S,L,L,U values are Monday values. Sunday and Monday is merged cells. Sunday and monday programs have 3 columns but they may have 4 or 5 columns sometimes. So I need to read under values.
Is this possible as programmatically in c#?
You should check out the EPPlus library - Create advanced Excel spreadsheets using .NET
https://github.com/JanKallman/EPPlus
There is a MergedCells property on the ExcelWorksheet class. You will need to evaluate this property and figure out the column size of Sunday & Monday.
Also, please see the following StackOverflow posts:
Get Merged Cell Area with EPPLus
Handle merged cells in Epplus Excel conversion to HTML
Below are the following libraries that could help you parse the merged cells with c#:
EPPlus, Aspose, Microsoft Interop, Spreadsheet gear
I need to read the data of particular range in excel file and upload them in database.
The required data does not start at A1 cell instead, they start at A15 and A14 is the header row for columns. there are seven columns with headers.
(I tried to read cells via "get_Range" option)
We need to read the data in each cell and do a row by row update in database.
There are thousands of files of same type in a specific folder.
I am trying to achieve this as C# Console app because this is just a one time job.
Here is the answer i found.
step 1 : Loop through each file in the source directory.
Step 2 : Add Excel Interop Reference. and Create Excel Application Class Object, and also for Workbook, and Range(for used range).
Step 3 : Use the Get Range() function and read the rows. (since this is solution is specific for a problem, the start and end ranges of rows and columns are well known)
Step 4 : Each read row can be constructed as a string till the end of the file.
OR
Insert can be done after reading each row.
step 5 : Get Connection String and Create SQLConnection Object to perform insert. Better to use Transaction-Commit.
Done. Thanks to all.
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.