Drop and replace table in Excel via OleDb - c#

I need to replace table created by OleDbCommand in Excel file. The new table has the same name, but could has different structure. I managed this by deleting sheet via Interop.Excel but there is problem when other sheets refer to this sheet. All formulas are lost. I noticed that creating new table via OleDbCommand creates new Defined name in Names property (Names manager). I've tried to create new table with other name, copy table headers and change name location in:
workbook.Names.Item(ShName, Type.Missing, Type.Missing).RefersTo=oldSheetRange
Where oldSheetRange is column headers range. Unfortunately when I try to insert new data rows they do not insert to the table (no error occurs).
Is there any option to replace table saving reffering formulas?
Regards, Kuba

Related

Reading CSV data with oleDBConnection into a C# DataSet and adding column headings

I have a .csv file that I am reading into C# via an OLEDBConnection. I am loading this into a DataSet. This step works fine. My data in the .csv file does not have any heading data/column headings. I want to add column headings to my DataSet in C# rather than directly into the .csv file. If I try to add column headings, then it just creates a new column on the end of the data, however I want to add the heading to the existing columns that already have data in it rather than create a new column.
Just access the column using index and the change the name
DataTable table = your datatable;
table.Columns[0].ColumnName = "Foo";

Keeping empty column names as such while reading the excel sheet data

I am reading an excel file and saving contents to database.
I have two columns , first column name is blank and second column name is A.
Both columns has rows under it .
When I am executing "select * from ["+excel[i]+"]") using oledbconnection,
empty column is automatically replaced with F1. I need both the columns and data as it is available from excel sheet.
How to avoid it?
I don't think there is a way to avoid this. This is a normal behaviour of OleDB when connected to Excel, if it finds empty columns, it will either take the first row as column name or generate some default names as of F1,F2,F3...etc

Adding a Row to an Excel Table

I am working on an Excel 2013/2015 VSTO workbook application. From data entered in a Windows form I'd like to create a new record in an existing Table on one of my worksheets.
How do I insert a new Table row into an Excel Table (not a simple worksheet array) using C# and VSTO?
The Microsoft.Office.Tools.Excel.ListObject provides the needed functionality. The table can be referenced and rows added as follows:
Microsoft.Office.Tools.Excel.ListObject lo = Globals.Sheet1.MyTable;
lo.ListRows.Add();
Optionally, the position of the new row can be specified (https://msdn.microsoft.com/en-us/library/microsoft.office.interop.excel.listrows.add.aspx). Default is at the end of the table.
IntelliSense did not show the Add() function in my case, which caused the confusion. Just type it in.

Import modified data in Excel to Database Table

I'm working on the function Import, i have an excel file which contains some data, that later will be edited by the user, I managed to do the import excel by SmartXLS in C# and update all data to SQL Server Database, however, what I did is to fetch all data in excel file and update all rows into the SQL Table, which affects to the performance and I also updated unedited rows.
I would like to ask that is there any way that I can get only modified cells, rows in Excel and update to the correponding data in SQL Table?
var workbook = new WorkBook();
workbook.read(filePath);
var dataTable = workbook.ExportDataTable();
Just a Scenarion, maybe it helps you to understand what gordatron and i were talking about:
Following Situation:
There is a Table "Products" wich is central storage place for product informations
and a table "UpdatedProducts" which structure looks exactly like "Products" table but data
maybe different. Think of following scenarion: you export product table to excel in the morning. the whole
day you delete, add, update products in your excel table. At the end of the day you want to re-import your excel
data to "Products" table. What you need:
delete all records from "UpdatedProducts"
insert data from excel to
"UpdatedProducts" (bulk insert if possible)
update the "Products"
table
Then a Merge-Statement could look like this:
MERGE Products AS TARGET
USING UpdatedProducts AS SOURCE
ON TARGET.ProductID = SOURCE.ProductID
WHEN MATCHED AND TARGET.ProductName <> SOURCE.ProductName OR TARGET.Rate <> SOURCE.Rate
THEN UPDATE SET TARGET.ProductName = SOURCE.ProductName,
TARGET.Rate = SOURCE.Rate
WHEN NOT MATCHED BY TARGET
THEN INSERT (ProductID, ProductName, Rate)
VALUES (SOURCE.ProductID, SOURCE.ProductName, SOURCE.Rate)
WHEN NOT MATCHED BY SOURCE
THEN DELETE
What this Statement does:
WHEN MATCHED:
Data exist in both tables, we update data in "Products" if ProductName or Rate is different
WHEN NOT MATCHED BY TARGET:
Data exist in staging table but not in your original table, we add them to "Products"
WHEN NOT MATCHED BY SOURCE:
Data exists in your original table but not in staging table, thy will be deleted from "Products"
Thanks a lot to http://www.mssqltips.com/sqlservertip/1704/using-merge-in-sql-server-to-insert-update-and-delete-at-the-same-time/ for this perfect example!

C# Typed DataSets: OleDBDataAdapter use the column names from the Typed DataSet and not ExcelSheet

I'm using VS 2010 with C# for a Windows Form application.
I need to load my data from the Excel sheet onto a DataSet. I created the DataSet using the DataSet designer and I manually added the tables and columns (FirstTable, Column1, Column2). Since I access the columns a lot, the code would be a lot cleaner to have a typed dataset instead of using an untyped one.
When I used the OleDBDataAdapter and populated the DataTable using Fill on FirstTable, Column1 and Column2 were empty and there were two additional columns that were from the Excel sheet (ExcelCol1, ExcelCol2). So unless, I gave the same excel columns names to FirstTable (instead of Column1 and Column2 if I called it ExcelCol1 and ExcelCol2), it would not populate the DataColumns that I created via the designer.
Is there any way to tell the DataSet to ignore the columns coming from Excel and just populate the already defined DataColumns?
IF that is not possible can I somehow connect the Excel sheet via a DataConnection to create the layout of the DataTables? The only thing I'm not sure about is that the excel file is user defined, so the user browses to the excel file to populate the DataSets. BUT the columns for all these excel files will always be the same. Hence I want to preset the layout using a Typed DataSet.
Ok, I think I figured out how to do that. I'm not sure if this is the cleanest method of doing it since I still have to hand-code it to assign the columns names i.e. there is no easy way to ignore the Excel column names but at least I am able to use typed datasets.
This link describes Table and Column mappings which is basically when you would like to use your own column names instead of the ones from Excel.
I would like to point out a few things, so I have given the following code.
Let's assume I have created a DataSet via the DataSet designer called MyDataSet.xsd. It has a table called FirstTable with columns Column1 and Column2. Then the following code can be used for the table mappings
MyDataSet myDS = new MyDataset();
//Some query commands using OleDB to get data from Excel
OleDbDataAdapter myAdapter = new OleDbDataAdapter(<OleDbCommand>);
DataTableMapping tableMap = myAdapter.TableMappings.Add("Table", myDS.FirstTable.TableName);
tableMap.ColumnMappings.Add("ExcelCol1", myDS.FirstTable.Column1.ColumnName);
tableMap.ColumnMappings.Add("ExcelCol2", myDS.FirstTable.Column2.ColumnName);
myAdapter.Fill(myDS);
I realised that when you read data from an Excel file, then in the DataTableMapping statement, the source name is always "Table" even though my sheetname/tablename is different on the Excel file.
To take advantage of the Typed Dataset, you can use commands like myDS.FirstTable.TableName and the same for the columns names instead of,
DataTableMapping tableMap = myAdapter.TableMappings.Add("Table", "FirstTable");
So if you change the table or column names in the DataSet you can use the refactoring utilities of VS.
I hope this helps. If there is a cleaner solution, I would appreciate any help but for now this fixed my problem.

Categories