Excel DNA - Argument works from spraedsheet, but not from vba - c#

This is a bit weird to me.
I have the following code:
public static object[,] dbMultipleSingleQueries(string strDBPath, object[] oSQL)
{
//This is needed for attaching a DB.
object[,] objOut;
objOut = new Object[1, 1];
try
{
//Prepare DB connection string
strDBPath = "Data Source=" +
#strDBPath +
";Version=3";
//SQL Objs
SQLiteConnection dbConnection = new SQLiteConnection(strDBPath);
SQLiteCommand dbCommand = null;
SQLiteDataAdapter dbAdapter = null;
DataTable table = new DataTable();
//For looping
int j = 0;
//Conn str
dbConnection.Open();
dbCommand = new SQLiteCommand(dbConnection);
while (j < oSQL.Length)
{
try
{
dbCommand.CommandText = oSQL[j].ToString();
dbCommand.CommandType = System.Data.CommandType.Text;
if (j == (oSQL.Length - 1))
{
dbAdapter = new SQLiteDataAdapter(dbCommand);
dbAdapter.Fill(table);
objOut = table2Array(table);
}
else
{
dbCommand.ExecuteNonQuery();
objOut[0, 0] = "Success!";
}
}
catch (Exception e2)
{
System.Console.WriteLine(e2.StackTrace.ToString());
objOut[0, 0] = e2.StackTrace.ToString();
}
j++;
};
dbConnection.Close();
dbConnection = null;
}
catch (Exception e)
{
objOut[0, 0] = e.StackTrace.ToString();
}
return objOut;
}
which works perfectly if i feed my arguments from a spreadsheet like this:
o = Application.Run("dbMultipleSingleQueries", "20130201.db", [test])
where [test] is a range in my workbook with queries that work and look something like this:
attach database 'a.db' as d1
select * from d1.main
now if i do the following in vba
Option Explicit
Sub Main()
Dim sql(1 To 2, 1 To 1)
sql(1, 1) = "attach database 'a.db' as d1"
sql(2, 1) = "select * from d1.main"
o = Application.Run("dbMultipleSingleQueries", "20130201.db", sql)
End Sub
this does not work. i get a "Type Mismatch" error. Any input why would be a huge help this is driving me nuts!

Your function prototype specifies that the second argument needs to be of type "Object[]" - but you are passing a variant that probably thinks it is a string array, based on the assignment.

Related

SQL Server CE not supporting ExecuteSQLCommand with EF?

I've been developing a C# WPF project with VS2015 using SQL Server Express LocalDb with Entity Framework. I have built a custom seeder for the database, that reads test data from an Excel file, that simply combines the Excel data into a command string, and this is inserted using context.Database.ExecuteSQLCommand.
Now, I was thinking of launching the project with SQL Server Compact Edition 4.0, but I find this command is not working anymore. Do I have to write my uploader again using SqlCeConnection and SqlCeCommand or am I missing something?
Also, from somewhere I have understood that with EF you can switch the SQL provider and the code would not need other changes. Am I in for more surprises down the road?
Example of the uploader command:
string cmd = "INSERT INTO Venues(Name, City, Telephone) Values ('X','Y','Z')"
context.Database.ExecuteSqlCommand(cmd);
The error:
There was an error parsing the query. [ Token line number = 2,Token line offset = 1,Token in error = INSERT ]
This is not just a testing issue, as I would want to include this uploader in the production version, too, for quick inserting of master data (e.g. employee list).
EDIT: Uploader code. If this can be done without resorting to raw SQL, that would be a good solution, too.
This loops through Excel sheets (named after entities) and columns (first row has property name) and rows 2->n (data). This handles the upload of basically any amount of data within Excel limitations. The point is that the code has no knowledge of the entities (might have been possible to parameterize DataContext too). Code might not be optimal, as I'm just a beginner, but has worked for me, except not with SQL CE. Editing to suit CE is not a big issue, but I wanted to ask for possibly better ways.
public static class ExcelUploader
{
static ArrayList data;
static List<string> tableNames;
public static string Upload(string filePath)
{
string result = "";
data = new ArrayList();
tableNames = new List<string>();
ArrayList upLoadData = ReadFile(filePath);
List<string> dataList = ArrayListToStringList(upLoadData);
using (var db = new DataContext())
{
using (var trans = db.Database.BeginTransaction())
{
try
{
foreach (var cmd in dataList)
{
Console.WriteLine(cmd);
db.Database.ExecuteSqlCommand(cmd);
}
db.SaveChanges();
trans.Commit();
}
catch (Exception e)
{
trans.Rollback();
result = e.Message;
MessageBox.Show(result);
}
}
}
return result;
}
private static ArrayList ReadFile(string fileName)
{
List<string> commands = new List<string>();
var xlApp = new Microsoft.Office.Interop.Excel.Application();
var wb = xlApp.Workbooks.Open(fileName, ReadOnly: true);
xlApp.Visible = false;
foreach (Worksheet ws in wb.Worksheets)
{
var r = ws.UsedRange;
var array = r.Value;
data.Add(array);
tableNames.Add(ws.Name);
}
wb.Close(SaveChanges: false);
xlApp.Quit();
return data;
}
private static List<string> ArrayListToStringList(ArrayList arrList)
{
List<string> result = new List<string>();
for(int tableAmount = 0;tableAmount<data.Count;tableAmount++)
{
result.Add(ArrayToSqlCommand(arrList[tableAmount] as Array, tableNames[tableAmount]));
}
return result;
}
private static string ArrayToSqlCommand(Array arr, string tableName)
{
int propertyRow = 1;
int firstDataRow = 2;
string command = "";
// loop rows
for (int rowIndex = firstDataRow; rowIndex <= arr.GetUpperBound(0); rowIndex++)
{
command += "INSERT INTO " + tableName + "(";
//add column names
for (int colIndex = 1; colIndex <= arr.GetUpperBound(1); colIndex++)
{
//get property name
command += arr.GetValue(propertyRow, colIndex);
//add comma if not last column, otherwise close bracket
if (colIndex == arr.GetUpperBound(1))
{
command += ") Values (";
}
else
{
command += ", ";
}
}
//add values
for (int colIndex = 1; colIndex <= arr.GetUpperBound(1); colIndex++)
{
//get property value
command += "'" + arr.GetValue(rowIndex, colIndex) + "'";
//add comma if not last column, otherwise close bracket
if (colIndex == arr.GetUpperBound(1))
{
command += ");";
}
else
{
command += ", ";
}
}
command += "\n";
}
return command;
}
}
There are two ways to use raw SQL queries I'd offer.
Initial data
1) Excel table
+=======+=======+===========+
| Name | City | Telephone |
|===========================|
| Adam | Addr1 | 111-11-11 |
|-------|-------|-----------|
| Peter | Addr2 | 222-22-22 |
+-------+-------+-----------+
2) SQL Server CE table
CREATE TABLE Venues
(
Id int identity primary key,
[Name] nvarchar(100) null,
City nvarchar(100) null,
Telephone nvarchar(100) null
);
3) Getting data from Excel
Here we're interested in getting array from Excel sheet. As soon as we get it, we can safely close Excel. The code assumes file "Employees.xlsx" to be next to executable file.
private object[,] GetExcelData()
{
xlApp = new Excel.Application { Visible = false };
var xlBook =
xlApp.Workbooks.Open(System.IO.Path.Combine(
Environment.CurrentDirectory,
"Employees.xlsx"));
var xlSheet = xlBook.Sheets[1] as Excel.Worksheet;
// For process termination
var xlHwnd = new IntPtr(xlApp.Hwnd);
var xlProc = Process.GetProcesses()
.Where(p => p.MainWindowHandle == xlHwnd)
.First();
// Get Excel data: it's 2-D array with lower bounds as 1.
object[,] arr = xlSheet.Range["A1"].CurrentRegion.Value;
// Shutdown Excel
xlBook.Close();
xlApp.Quit();
xlProc.Kill();
GC.Collect();
GC.WaitForFullGCComplete();
return arr;
}
Now you can use one of the ways to generate query.
Option 1. Use ExecuteSqlCommand
When using ExecuteSqlCommand, it's advisable to use parameterized queries to avoid errors. You can pass explicitly created SqlCeParameter or just pass a value.
private void UseExecuteSqlCommand()
{
object[,] arr = GetExcelData();
using (var db = new EmpContext())
{
db.Database.Initialize(true);
int count = 0;
string sql = "INSERT INTO Venues (Name, City, Telephone) " +
"VALUES (#name, #city, #phone);";
// Start from 2-nd row since we need to skip header
for (int r = 2; r <= arr.GetUpperBound(0); ++r)
{
db.Database.ExecuteSqlCommand(
sql,
new SqlCeParameter("#name", (string)arr[r, 1]),
new SqlCeParameter("#city", (string)arr[r, 2]),
new SqlCeParameter("#phone", (string)arr[r, 3])
);
++count;
}
conn.Close();
MessageBox.Show($"{count} records were saved.");
}
}
Option 2. Use DbConnection
If you want your code to be more generic, you can create method which would accept DbConnection. This will allow to pass either SqlConnection or SqlCeConnection. But the code becomes more verbose because we can't use constructors since these classes are abstract.
private void UseDbConnection()
{
object[,] arr = GetExcelData();
using (var db = new EmpContext())
{
db.Database.Initialize(true);
int count = 0;
string sql = "INSERT INTO Venues (Name, City, Telephone) " +
"VALUES (#name, #city, #phone);";
DbParameter param = null;
DbConnection conn = db.Database.Connection;
conn.Open();
DbCommand command = conn.CreateCommand();
command.CommandText = sql;
command.CommandType = CommandType.Text;
// Create parameters
// Name
param = command.CreateParameter();
param.ParameterName = "#name";
command.Parameters.Add(param);
// City
param = command.CreateParameter();
param.ParameterName = "#city";
command.Parameters.Add(param);
// Telephone
param = command.CreateParameter();
param.ParameterName = "#phone";
command.Parameters.Add(param);
// Start from 2-nd row since we need to skip header
for (int r = 2; r <= arr.GetUpperBound(0); ++r)
{
command.Parameters["#name"].Value = (string)arr[r, 1];
command.Parameters["#city"].Value = (string)arr[r, 2];
command.Parameters["#phone"].Value = (string)arr[r, 3];
command.ExecuteNonQuery();
++count;
}
conn.Close();
MessageBox.Show($"{count} records were saved.");
}
}
You can also use ordinal positions for parameters which eliminates creating parameters names and makes code much shorter:
private void UseDbConnection()
{
object[,] arr = GetExcelData();
using (var db = new EmpContext())
{
db.Database.Initialize(true);
int count = 0;
// Take a note - use '?' as parameters
string sql = "INSERT INTO Venues (Name, City, Telephone) " +
"VALUES (?, ?, ?);";
DbConnection conn = db.Database.Connection;
conn.Open();
DbCommand command = conn.CreateCommand();
command.CommandText = sql;
command.CommandType = CommandType.Text;
// Create parameters
command.Parameters.Add(command.CreateParameter());
command.Parameters.Add(command.CreateParameter());
command.Parameters.Add(command.CreateParameter());
for (int r = 2; r <= arr.GetUpperBound(0); ++r)
{
// Access parameters by position
command.Parameters[0].Value = (string)arr[r, 1];
command.Parameters[1].Value = (string)arr[r, 2];
command.Parameters[2].Value = (string)arr[r, 3];
command.ExecuteNonQuery();
++count;
}
conn.Close();
MessageBox.Show($"{count} records were saved.");
}
}
P.S.
I didn't check whether the underlying connection is opened, but it's a good idea to do so.
Based on JohnyL's excellent input, I was able to modify my code so that it works with either SQL Server Express and and SQL Server CE. I'll put my new code as an answer, as I had to parameterize it further, as I couldn't write the property names in the code either. But this was a simple step, once I got the idea from JohnyL. Not sure though, if the database writing operation should be wrapped inside a DbTransaction, but this worked for now.
public static class ExcelUploader
{
static ArrayList data;
static List<string> tableNames;
static List<DbCommand> cmdList = new List<DbCommand>();
static DbConnection conn;
public static void Upload(string filePath)
{
data = new ArrayList();
tableNames = new List<string>();
//get Excel data to array list
ArrayList upLoadData = ReadFile(filePath);
using (var db = new DataContext())
{
conn = db.Database.Connection;
//transform arraylist into a list of DbCommands
ArrayListToCommandList(upLoadData);
conn.Open();
try
{
foreach (var cmd in cmdList)
{
//Console.WriteLine(cmd.CommandText);
cmd.ExecuteNonQuery();
}
}
catch (Exception e)
{
var result = e.Message;
MessageBox.Show(result);
}
}
}
//opens Excel file and reads worksheets to arraylist
private static ArrayList ReadFile(string fileName)
{
List<string> commands = new List<string>();
var xlApp = new Microsoft.Office.Interop.Excel.Application();
var wb = xlApp.Workbooks.Open(fileName, ReadOnly: true);
xlApp.Visible = false;
foreach (Worksheet ws in wb.Worksheets)
{
var r = ws.UsedRange;
var array = r.Value;
data.Add(array);
tableNames.Add(ws.Name);
}
wb.Close(SaveChanges: false);
xlApp.Quit();
return data;
}
//transforms arraylist to a list of DbCommands
private static void ArrayListToCommandList(ArrayList arrList)
{
List<DbCommand> result = new List<DbCommand>();
for (int tableAmount = 0; tableAmount < data.Count; tableAmount++)
{
ArrayToSqlCommands(arrList[tableAmount] as Array, tableNames[tableAmount]);
}
}
private static void ArrayToSqlCommands(Array arr, string tableName)
{
//Excel row which holds property names
int propertyRow = 1;
//First Excel row with values
int firstDataRow = 2;
string sql = "";
DbCommand cmd = conn.CreateCommand();
sql += "INSERT INTO " + tableName + "(";
//add column names to command text
for (int colIndex = 1; colIndex <= arr.GetUpperBound(1); colIndex++)
{
//get property name
sql += arr.GetValue(propertyRow, colIndex);
//add comma if not last column, otherwise close bracket
if (colIndex == arr.GetUpperBound(1))
{
sql += ") Values (";
}
else
{
sql += ", ";
}
}
//add value parameter names to command text
for (int colIndex = 1; colIndex <= arr.GetUpperBound(1); colIndex++)
{
//get property name
sql += "#" + arr.GetValue(propertyRow, colIndex);
//add comma if not last column, otherwise close bracket
if (colIndex == arr.GetUpperBound(1))
{
sql += ");";
}
else
{
sql += ", ";
}
}
//add data elements as command parameter values
for (int rowIndex = firstDataRow; rowIndex <= arr.GetUpperBound(0); rowIndex++)
{
//initialize command
cmd = conn.CreateCommand();
cmd.CommandText = sql;
cmd.CommandType = CommandType.Text;
for (int colIndex = 1; colIndex <= arr.GetUpperBound(1); colIndex++)
{
//set parameter values
DbParameter param = null;
param = cmd.CreateParameter();
param.ParameterName = "#" + (string)arr.GetValue(propertyRow, colIndex);
cmd.Parameters.Add(param);
cmd.Parameters[param.ParameterName].Value = arr.GetValue(rowIndex, colIndex);
}
//add command to command list
cmdList.Add(cmd);
}
}
}

Date-picker using select statement oracle

I'm trying to implement date-picker functionality in my project, but I can't do it quite right. I'm trying to pass the date-picker value in my oracle string so that it will compare with my db column and return results on the date criteria...
Whenever I pass it to the select statement it won't generate errors particularly but on button click it doesn't perform anything except it shows "not connected".
str = "Select * from sania.doctor where APPOINTMENT_DATE = "+ datepicker1.value;
It is clear it is logical mistake but I'm new to this C# concepts I need someone to tell me how to pass it and then display the results as well.
private void button1_Click(object sender, EventArgs e)
try
{
OracleCommand com;
OracleDataAdapter oda;
string ConString = "Data Source=XE;User Id=system;Password=sania;";
OracleConnection con = new OracleConnection(ConString);
{
// string id = dateTimePicker1.Text.Trim();
con.Open();
// str = "Select * from sania.doctor where APPOINTMENT_DATE = " + dateTimePicker1.value;
str = "select * from sania.doctor where APPOINTMENT_DATE to_date('"+dateTimePicker1.Value.ToString("yyyyMMdd") + "', 'yyyymmdd')";
com = new OracleCommand(str);
oda = new OracleDataAdapter(com.CommandText, con);
dt = new DataTable();
oda.Fill(dt);
Rowcount = dt.Rows.Count;
//int val = 0;
for (int i = 0; i < Rowcount; i++)
{
dt.Rows[i]["APPOINTMENT_DATE"].ToString();
//if (id == dateTimePicker1.Value)// this LINE SHOWS ERROR--because it is a string and I am using date with it. Don't know conversion
// {
// val = 1;
//}
}
// if (val == 0)
// { MessageBox.Show("INVALID ID"); }
// else
// {
DataSet ds = new DataSet();
oda.Fill(ds);
if (ds.Tables.Count > 0)
{
dataGridView1.DataSource = ds.Tables[0].DefaultView;
}
else { MessageBox.Show("NO RECORDS FOUND"); }
}
}
//}
catch (Exception)
{ MessageBox.Show("not connected"); }
}
Do not put values into SQL directly, use bind variables/parametes instead. For Oracle:
// :prm_Appointment_Date bind variable declared within the query
String str =
#"select *
from sania.doctor
where Appointment_Date = :prm_Appointment_Date";
....
using(OracleCommand q = new OracleCommand(MyConnection)) {
q.CommandText = str;
// datepicker1.Value passed into :prm_Appointment_Date via parameter
q.Parameters.Add(":prm_Appointment_Date", datepicker1.Value);
...
}
Doing like that you can be safe from either SQL Injection or Format/Culture differences

How to execute a ExecuteNonQuery with List parameters in Where Clause

My code looks like this:
var settings = ConfigurationManager.ConnectionStrings["InsurableRiskDB"];
string server = ConfigurationManager.AppSettings["Server"];
string cs = String.Format(ConfigurationManager.AppSettings[settings.ProviderName], ConfigurationManager.AppSettings[server]);
SqlConnection connection = new SqlConnection(cs);
string PolicyKeys = "";
for (int i = 0; i < keys.Count(); i++)
{
if (i == keys.Count() - 1)
PolicyKeys += keys[i] ;
else
PolicyKeys += keys[i] + ", ";
}
//have to change the code to pull the user's NBK.
string user = "'DATALOAD'";
const string updateQuery = #"UPDATE [InsurableRisk].[dbo].[Policy]
SET [InsuranceCarrierKey] = #ToKey
,[AuditUser] = #User
,[AuditDate] = SYSDATETIME()
WHERE PolicyKey in (#PolicyKeys) and InsuranceCarrierKey = #FromKey";
using (connection)
{
using (SqlCommand dataCommand = new SqlCommand(updateQuery, connection))
{
dataCommand.Parameters.AddWithValue("#ToKey", toKey);
dataCommand.Parameters.AddWithValue("#User", user);
dataCommand.Parameters.AddWithValue("#PolicyKeys", PolicyKeys);
dataCommand.Parameters.AddWithValue("#FromKey", fromKey);
connection.Open();
dataCommand.ExecuteNonQuery();
connection.Close();
}
}
res = true;
}
catch (Exception ex)
{
MessageBox.Show("There is an error while try in save the changes " + ex.Message, "Error Message", MessageBoxButtons.OKCancel);
res = false;
}
return res;
Now, when i run this code, it says query is unable to execute. It throws and exception stating, it is unable to convert NVarchar to int for variable #PolicyKeys
Any suggestions as to what i am missing in this code?
Typically, in SQL you'd write an IN statement like this:
WHERE SomeColumn IN ('A', 'B', 'C')
What you're doing is the equivalent of this in SQL (which won't work):
WHERE SomeColumn IN ('A, B, C')
Change your SQL statement accordingly: (modified from this answer)
WHERE PolicyKey in ({0})
And then add your parameters in a loop, like this:
var parameters = new string[keys.Count()];
for (int i = 0; i < keys.Count(); i++)
{
parameters[i] = string.Format("#Key{0}", i);
cmd.Parameters.AddWithValue(parameters[i], keys[i]);
}
cmd.CommandText = string.Format(updateQuery, string.Join(", ", parameters));

"An INSER INTO query cannot contain a multi-valued Field" OleDBException

I get the following Error when i try to insert Data in one of my tables "An INSERT INTO query cannot contain a multi-valued Field", The other tables are working fine.
I am using an Access 2010 DB, Field Types are Text, Date, Number, Autonumber, Currency.
Do I miss something ?
public void CreateNewSystemWithDefaultValues(String IP)
{
String[] Convert = NetworkInformation.GETDNSFfromIP(IP).Split('.');
DataTable Data = SystemsAccessDB.GETAllDataFromDBWithOption("Systems", "Where 1 = 2");
DataRow DataR;
DataR = Data.NewRow();
DataR["SystemName"] = Convert[0];
DataR["SystemSerialNumber"] = #"n/a";
DataR["SystemCreationDate"] = System.DateTime.Now.Date;
DataR["SystemIPAdress"] = IP;
DataR["SystemDRACAdress"] = #"n/a";
DataR["SystemState"] = "Unknown";
DataR["SystemNIC"] = #"n/a";
DataR["SystemHDDController"] = #"n/a";
DataR["SystemServiceTag"] = #"n/a";
DataR["SystemWikiURL"] = #"https://wikiurl";
DataR["SystemInstallationMedia"] = #"\\Networkpath\";
DataR["SystemMonitoring"] = #"n/a";
DataR["SystemTypeID"] = 6;
DataR["SystemsCPUID"] = 6;
DataR["SystemsMemoryID"] = 6;
DataR["SystemsDowntimeID"] = 9;
DataR["SystemOSID"] = 9;
DataR["SystemLocationID"] = 6;
DataR["SystemContactDataIDHardware"] = 1;
Data.Rows.Add(DataR);
SystemsAccessDB.ADDDataToDB("Systems", Data);
}
public static void ADDDataToDB(String Table, DataTable Data)
{
using (OleDbConnection DBConnection = new OleDbConnection(GetConnectionString()))
{
OleDbDataAdapter DataAdapter = new OleDbDataAdapter();
DataAdapter.SelectCommand = new OleDbCommand("SELECT * FROM "+Table+"", DBConnection);
OleDbCommandBuilder CommandBuilder = new OleDbCommandBuilder(DataAdapter);
CommandBuilder.GetInsertCommand();
try
{
DBConnection.Open();
DataAdapter.Update(Data);
}
catch (OleDbException e)
{
MessageBox.Show(e.Message);
}
catch (Exception e)
{
MessageBox.Show(e.Message);
}
}
}

Microsoft OLEDB Error External table is not in the expected format

I have wrote a code that can read an excel 2007 file using Microsoft Data Access Engine the below code snippet works fine for most of the files but it happens to work for most of the excel files i.e. .xlsx,.xls but when it fails at objConn.Open(); for excel files that have excel formatting problems please refer to the image below
It would failed to open the ole Db Connection stating error External table is not in the expected format . One more problem with this import procedure is that
OleDbCommand objCmdSelect = new OleDbCommand("SELECT * FROM "+ SelectionSheet, objConn);
is not able to read sheets starting with spaces any help with solving this issue would be highly appreciated.
public DataTable ReadExcel(string Path, ArrayList IgnoreString, ArrayList IgnoreColumn)
{
DataTable dtReturn = new DataTable();
DataTable dtPrintable = new DataTable();
DataTable dtTemp = new DataTable();
try
{
string sConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;" +
"Data Source=" + Path + ";" + "Extended Properties=\"Excel 12.0 Xml;HDR=YES;IMEX=1;\"";
OleDbConnection objConn = new OleDbConnection(sConnectionString);
objConn.Open();
DataTable dtSheetnames = objConn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
DataTable dtTesting = objConn.GetOleDbSchemaTable(OleDbSchemaGuid.DbInfoLiterals, new object[] {});
DataTable dtTesting2 = objConn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables_Info, new object[] { });
string SelectionSheet = dtSheetnames.Rows[0][2].ToString();
if (SelectionSheet.Contains("'") )
{
SelectionSheet = SelectionSheet.Remove(0, 1);
SelectionSheet = "[" + SelectionSheet;
SelectionSheet = SelectionSheet.Remove(SelectionSheet.Length - 1, 1);
// -- Mod by zeemz on 23 dec
// string PrintArea = SelectionSheet + "Print_Area]";
SelectionSheet = SelectionSheet + "]";
}
else
{
SelectionSheet = "["+ SelectionSheet + "]";
}
//OleDbCommandBuilder objCmdBuilder = new OleDbCommandBuilder(
OleDbCommand objCmdSelect = new OleDbCommand("SELECT * FROM "+ SelectionSheet, objConn);
OleDbDataAdapter objAdapter = new OleDbDataAdapter();
DataSet objDataSet = new DataSet();
DataSet PrintAreads = new DataSet();
objAdapter.SelectCommand = objCmdSelect;
objAdapter.Fill(objDataSet);
// -- Mod by zeemz on 23 dec
//objCmdSelect.CommandText = "SELECT * FROM " + PrintArea;
//objAdapter.Fill(PrintAreads);
objConn.Close();
dtReturn = objDataSet.Tables[0].Copy();
// dtPrintable = PrintAreads.Tables[0].Copy();
// -- Mod by zeemz on 23 dec
//if (dtPrintable.Columns.Count != dtReturn.Columns.Count)
//{
// int TotalPrintable = dtPrintable.Columns.Count;
// int TotalComing = dtReturn.Columns.Count;
// int StartRemovingPos = TotalComing - TotalPrintable;
// for (int i = TotalPrintable; dtPrintable.Columns.Count != dtReturn.Columns.Count; i++)
// {
// dtReturn.Columns.RemoveAt(i);
// i = i - 1 ;
// }
//}
int iCount = 0;
while (iCount <= dtReturn.Rows.Count - 1)
{
if (isRowEmpty(dtReturn.Rows[iCount]))
{
dtReturn.Rows.RemoveAt(iCount);
}
else
{
iCount += 1;
}
}
//now applying the filters
//column ignore
for (int i = IgnoreColumn.Count - 1; i >= 0; i--)
{
dtReturn.Columns.RemoveAt((int)IgnoreColumn[i]);
}
//string ignore
for (int i = IgnoreString.Count - 1; i >= 0; i--)
{
for (int j = dtReturn.Rows.Count - 1; j >= 0; i--)
{
foreach (DataColumn dCol in dtReturn.Columns)
{
if (dtReturn.Rows[j][dCol.ColumnName].ToString().ToLower().Contains(IgnoreString[i].ToString().ToLower()))
{
dtReturn.Rows.RemoveAt(j);
break;
}
}
}
}
/* Hack to get rid of DateTime Columns */
// added by zeemz
dtTemp = dtReturn.Clone();
dtTemp.Clear();
foreach (DataColumn tempColumn in dtTemp.Columns)
{
// if (tempColumn.DataType == typeof(DateTime))
// {
tempColumn.DataType = typeof(String);
// }
}
foreach (DataRow tempRow in dtReturn.Rows)
{
DataRow insRow = dtTemp.NewRow();
foreach (DataColumn tempColumn in dtReturn.Columns)
{
if (tempColumn.DataType == typeof(DateTime))
{
if (!String.IsNullOrEmpty(tempRow[tempColumn.ColumnName.ToString()].ToString()))
{
insRow[tempColumn.ColumnName.ToString()] = Convert.ToDateTime(tempRow[tempColumn.ColumnName.ToString()].ToString()).ToString("yyyyMMddhhmmss");
}
else
{
insRow[tempColumn.ColumnName.ToString()] = "";
}
}
else
{
insRow[tempColumn.ColumnName.ToString()] = tempRow[tempColumn.ColumnName.ToString()].ToString();
}
}
dtTemp.Rows.Add(insRow);
}
}
catch (Exception ex)
{
throw ex;
}
return dtTemp;
}
I happen to find out the problem exists when you modify the xlsx file manually or programatically without using excel once you modify the xlsx the format doesn't stay intact and the above mentioned error comes up because OleDbDataAdapter is unable to handle the modified file and Excel it self can fix the corrupt files shows the file as expected.

Categories

Resources