Example of Reading Data and Writing Directly Into Excel - c#

I currently have a routine which reads rows/columns and writes into a SQL table from a SELECT statement.
We were thinking of then reading the SQL table and updating an empty Excel worksheet. What I would like to do is read and then update the data directly into Excel.
My program currently does the following:
Opening the workbook.
Accessing the different worksheets.
Saving As a new workbook name.
Closing Excel.
I just need an example that:
will allow the first row to be the column names
then read out the data into the various cells for each row.

I do not recommend using COM Interop either.
You can find here a sample about exporting dataset to Excel in C#.
It requires an Excel tool named EasyXLS.

to open the file you can do it like that:
Dim exAppl As New Excel.Application
exAppl.Visible = True
Dim exMappe As Excel.Workbook = exAppl.Workbooks.Open("C:\... .xlsx", , False)
You can acces to a Cell with
Console.WriteLine(exAppl.Range("A2").Value())
or when you whant to go throw it use something like that:
For i As Integer = 1 To exAppl.Rows.Count
Dim a As Excel.Range = exAppl.Rows(i)
For j As Integer = 1 To a.Columns.Count
Dim b As Excel.Range = a.Columns(j)
Console.WriteLine(b.Value)
Next
Next

Related

How to use SSIS script task to delete second row in Excel destination? SQL Server 2012

I have a simple package that extracts data from SQL Server and writes it to Excel spreadsheet.
Why am I doing this: the problem is that the value of one of the column is greater than 255 characters, which causes an error. I already tried different ways to find a solution, but so far without success.
So I created dummy row in my Excel template that is able to accept more than 255 characters. After I load the data, I need to delete that dummy row.
I do not know much about C#. How can I delete second row in Excel destination by using SSIS script task C#? Do I need to create variables that hold the path folder and file name?
And then how can I map those variables to my C# code?
You can use Microsoft.Office.Interop.Excel.dll library inside the Script Task to achieve this.
You can use a similar code:
Note: I assumed that the file path variable name is FilePath. Remember to select the FilePath variable in the Script Task ReadOnly Variables (in the Script editor). Also don't forget to add Microsoft.Office.Interop.Excel.dll as a reference inside the script task
Imports Microsoft.Office.Interop
Public Sub Main()
Dim strFile as String = Dts.Variables("FilePath").Value
Dim m_XlApp = New Excel.Application
m_XlApp.visible = False
m_XlApp.DisplayAlerts = False
Dim m_xlWrkbs As Excel.Workbooks = m_XlApp.Workbooks
Dim m_xlWrkb As Excel.Workbook
m_xlWrkb = m_xlWrkbs.Open(strFile)
m_xlWrkb.DoNotPromptForConvert = true
Dim m_XlWrkSheet As Excel.Worksheet = m_xlWrkb.Worksheets(1)
m_XlWrkSheet.Cells(2, 1).EntireRow.Delete(Excel.XlDeleteShiftDirection.xlShiftUp)
m_xlWrkb.Save()
m_xlWrkb.Close(SaveChanges:=True)
Marshal.ReleaseComObject(m_xlWrkb)
Marshal.ReleaseComObject(m_xlWrkbs)
m_XlApp.Quit()
Marshal.ReleaseComObject(m_XlApp)
End Sub
I got the same damn problem.
Like you, I created dummy row in my Excel template that is able to accept more than 255 characters.
However, I works on Visual Studio 2008 and I can't install anythings on my computer.
My solution to delete the dummy row is to set in it's first column the value "DummyRow" and create this following macro in the Excel template:
Private Sub Workbook_Open()
Call SupprDummyRow
End Sub
Sub SupprDummyRow()
x = Range("A2").Value 'First row after the titles, first column
y = Range("A3").Value 'Second row after the titles, first column
If (x = "DummyRow" And y <> "") Then 'The Dummy Row is present AND the next row have value (we are in the export file)
Range("A2").EntireRow.Delete 'Delete the lign
End If
End Sub
Note that on my situation the first column have always a value (no empty string).
Hope this help!
Best regards,
Try this to increase the column length on the Excel destination. This way you would not even need to add your dummy record to the excel file and later delete it.
Right Click on your Excel Destination.
Click on "Show Advanced Editor".
In the Advanced Editor, go to the "Input and Output Properties" tab.
Expand the "External Column" of you Excel Destination Section and adjust the Length property values of the required column. You can also change data-types if needed. Please find the screenshot for the same.
Try this and let me know if it worked.
I created dummy row in my Excel template Which is able to accept more than 255 characters. After export data to excel file, delete dummy row from excel with SSIS scripts task.
Pass the exel file as variable like below immage
Write below code to delete 2 number row. worksheet.Rows[2].Delete();

Create Excel workbook without any sheet

Is there a way to create an Excel workbook without any sheets in it?
This is the code that I use to create the workbook:
excelApp = new Microsoft.Office.Interop.Excel.Application();
excelBook = excelApp.Workbooks.Add();
I tried also adding
excelApp.SheetsInNewWorkbook = 0;
before the creation of the excelBook but the minimum value is 1 so the program crashes.
EDIT:
Tried also to delete the first sheet as soon as it is created but still doesn't work
Sheets excelSheetsToDelete = excelBook.Sheets[1];
excelSheetsToDelete.Delete();
I would like to be able to add my sheets with my names later without having to rename the first one.
You can't create an Excel without any sheet, Excel must contain at least one sheet. Try to delete single sheet in Excel application (desktop). You won't do that.
Like people have already said, Excel must contain at least 1 visible worksheet at all times. Since it seems like you just want to create a workbook, and manually specify your sheet name without having to rename the one created automatically, I wrote this quick VB Script that may work for you.
Dim objShell, objExcel, objWorksheet, strSheetName
strSheetName = InputBox("Enter a name for your new Worksheet:")
Set objShell = WScript.CreateObject( "WScript.Shell" )
objShell.Run("EXCEL.EXE")
WScript.Sleep 3000 'Wait for new excel file to open
Set objExcel = GetObject(, "Excel.Application")
Set objWorksheet = objExcel.ActiveWorkbook.Worksheets(1)
objWorksheet.Name = strSheetName
What this does is prompt you to enter a name for your new sheet. It then runs a new instance of Excel and sets the first worksheet of the newly created file as the name you specified.
If Excel includes 3 sheets when creating new workbooks, you can change this to 1 by going in any excel worbook and clicking - File > Options > General - and look for the "When the creating new workbooks" separator. There will be an option "Include this many sheets" which you can change to 1.
Also, to confirm what people have already said, if you try and change this value to 0, it will tell you "The entry must be greater than or equal to 1" meaning all workbooks must contain at least 1 visible worksheet. Hope this helped.

Which way to read a cell from Excel using C#?

I have found two ways those were being used by people if we want to read or write to a cell in an excel.
Declaration:
Excel.Application ExcelApp = new Excel.Application();
Excel.Workbook srcWorkBook = ExcelApp.Workbooks.Open(#"C:\test.xls");
Excel.Worksheet srcWorkSheet = srcWorkBook.Worksheets[1];
Excel.Range srcRange = srcWorkSheet.UsedRange;
Usage 1:
srcWorkSheet.Cells[1, 1].value2 = "foo bar";
Usage 2:
srcRange.Cells[2, 2].Value2 = "foo bar";
Which one is the best way to use ? or it's all fine in .NET ?
The two ways are very different.
srcWorkSheet.Cells[1, 1].value2 = "foo bar";
The 1. usage refers to the A1 cell of the first worksheet.
MSDN Worksheets.Cells property Excel
srcRange.Cells[2, 2].Value2 = "foo bar";
The 2. usage takes the cell on the 2. row, 2. column of the UsedRange. If the UsedRange in Excel is B2:D5, it would put value at C3:
MSDN Worksheets.Range Property Excel
Having a variable named Range as the Range class is really not a great idea. The same goes for WorkSheet and WorkBook.
Either option will work, but they get messy as soon as you have to modify the layout of the worksheet.
If it's an option, I like to add named ranges. This works particularly well if you're using a template where you can modify the "starting" state of the workbook.
Let's say you have a series of columns, and one of them contains the "foo" value. You can add a name like "fooColumn" to the entire column or the top cell in the column.
Then you can get the column number using
worksheet.Range("fooColumn").Column
That protects you from having to manually edit column or row numbers all over the place if you move elements around on your worksheet.
And to second what others have said, use EPPlus instead of Interop. You can still use named ranges. But EPPlus is good and Interop can bring all sorts of pain when COM objects aren't released. Interop automates an application that manipulates the file. EPPlus just works with the file.

Excel Interop: Get named table (Range) from specific workbook

I'm trying to create a WinForms application that interacts with Excel using the Excel Object Library v.15.
I'm using this to get the Excel Application object
(Application)System.Runtime.InteropServices.Marshal.GetActiveObject("Excel.Application");
And I know I can get the Range for the named table I want by using
_application.Range["MyTableName"];
Now, the problem I'm facing is that if I have two workbooks opened at the same time and each one of them has a named table with the same name, I don't know which Range will be returned.
The Excel application is unique, so I cannot simply try to get the process based on the window title or something like that.
I can get the Workbook object based on its title:
_application.Workbooks.Cast<Workbook>().FirstOrDefault(w.Name.Equals(title))
However I cannot access the Ranges of a particular Workbook.
I know I could iterate through the Sheets of the Workbook element trying to find the table but I was wondering if there was another "cleaner" way.
I would appreciate any guideline on this.
Thanks,
Will
The simplest/most direct way I can think of would be to iterate through the Names collection, check the parent, and move on.
E.g:
For Each NamedRange as Range in MyApplication.Names
Dim Check as Object = TryCast(NamedRange.Parent, Workbook)
If Check Is Nothing Then
Check = TryCast(NamedRange.Parent, Worksheet)
Check = TryCast(Check.Parent, Workbook)
End If
If Not Check Is Nothing AndAlso Check.Name = "MyWorkbook" Then
'Do something
End If
Next

Copy cells in excel using C#

How to copy to specific row in target sheet?
I need to copy A1 to J10 from a sheet in one excel to location starting from A15 in second excel sheet. How can I achieve this in c#? In the below Copy method there seems to be no option to specify the location in target excel sheet.
ObjWorkSheet = (Microsoft.Office.Interop.Excel.Worksheet)ObjWorkBookTemp.Sheets[1];
ObjWorkSheet.Copy(Type.Missing, ObjWorkBookGeneral.Sheets[1]);
I think you are using the wrong method here... you want to use a Paste method not a copy method.
Try the Range.PasteSpecial method... should do the trick for you.
Something like this...
Excel.Range sourceRange = firstWorksheet.get_Range("A1", "J10");
Excel.Range destinationRange = secondWorksheet.get_Range("A15", "J25");
sourceRange.Copy(Type.Missing);
destinationRange.PasteSpecial(Microsoft.Office.Interop.Excel.XlPasteType.xlPasteFormulas, Microsoft.Office.Interop.Excel.XlPasteSpecialOperation.xlPasteSpecialOperationNone, false, false);

Categories