I am certain I have missed something obvious.
A simple task is before me: 'Upload an Excel (2003) file via ASP.NET on a Forms page and push the contents of that file to a DataTable in preparation for data- validation / storage'.
Those operations work fine already when applied to a locally stored edition of the file -- for that I simply utilize the OleDbConnection-ConnectionString "String.Format("Provider=Microsoft.Jet.OLEDB.4.0;Data Source={0};Extended Properties=Excel 8.0;", fileName)" from an OleDbDataAdapter.
However, trying to repeat that with an uploaded edition of the very same file (via a FileUpload control), on the line where I fill the OleDbDataAdapter I receive the error ["The Microsoft Jet database engine could not find the object "Sheet1$". Make sure the object exists and that you spell its name and the path name correctly."] An error so generic and painful -- still I'm unsure where to look next. I am guessing the connection-string structure is illegitimate for an uploaded file.
I searched through StackOverflow and MSDN and even around the web with no success thus far, but the search terms may be overly ubiquitous. Am I required to actually find a local repository for saving the uploaded file to prior to attempting a parse of it's content? Can I not simply construct a connection to a 'file in memory'? In case it concerns the answer, the uploaded files are not anticipated to ever exceed 200 kb in size.
Sincere thanks in advance for any assistance provided...
What I do in this situation is build a Parser class that will temporarily save the file, process it, then delete that temporary file when disposed. Something like:
public class ExcelParser : IDisposable
{
string filename;
string connStr = "Provider=Microsoft.ACE.OLEDB.12.0; Data Source={0}; Extended Properties=\"Excel 12.0 Xml;HDR=YES\"";
public ExcelParser(HttpPostedFile file)
{
filename = String.Format("{0}{1}.xlsx", System.IO.Path.GetTempPath(), Guid.NewGuid().ToString());
file.SaveAs(filename);
}
public MyData Process()
{
OleDbConnection conn = new OleDbConnection(String.Format(connStr, filename));
conn.Open();
OleDbCommand cmd = new OleDbCommand("Select * From [Sheet1$]", conn);
OleDbDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
// Build Data to return
}
reader.Close();
conn.Close();
return data; // Return data you built
}
public void Dispose()
{
File.Delete(filename);
}
}
You could then use it as such:
using (ExcelParser parser = new ExcelParser(file))
{
var results = parser.Process();
// Do stuff
}
Related
I have a program which is supposed to open, edit, create and save access databases. For saving I copy an empty database with just the tables (just to avoid going through the hassle of creating every table and column etc) and try to fill it with values via the TableAdapterManager.UpdateAll method.
string _TemplateConnectString = #"Provider=Microsoft.Jet.OLEDB.4.0;Data Source={0};";
_connection = new OleDbConnection(string.Format(_TemplateConnectString, dlg.FileName));
_connection.Open();
DataSet1TableAdapters.TableAdapterManager tam=new TableAdapterManager();
tam.Connection = _connection;
try
{
tam.UpdateAll(dataset);
}
catch (System.Exception ex)
{
MessageBox.Show("Update failed");
}
It finishes with no exceptions but the values don't get inserted into the new database.
Also as far as I know the UpdateAll method only updates modified row so if I open some db and it inserts it's rows, it will not take them into account even though there are not in the database that I am trying to fill.
I have also tried filling the database with the ADODB and ADOX extensions but all the solutions I found with those was a lot of hardcoding and no regards for hierarchy, keys, etc.
Is there a way to force insert everything in the new database?
Is your template database in the Visual Studio project directory? It might have something to do with Visual Studio copying the database to the bin/debug or bin/release folder...
Try to use the right Data source database name, here an
example with an excel file:
cnn.Open "Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=c:\somepath\ExcelFile.xls;" & _
"Extended Properties=""Excel 8.0;HDR=Yes;"";"
A clumsy solution but it works. I iterate the tables of the dataset and save the via an sql string generator like this:
void SaveTable(DataTable dt)
{
string[] inserts;
try
{
inserts = SqlHelper.GenerateInserts(dt, null, null, null);
foreach (string s in inserts)
{
OleDbCommand cmd = new OleDbCommand();
cmd.CommandText = s;
cmd.Connection = _connection;
int n = cmd.ExecuteNonQuery();
}
}
catch (Exception e)
{
SaveOk = false;
}
}
I found the SqlHelper somewhere on this site, but completely lost where, unforunately. So here is the pastebin with it https://pastebin.com/iCMVuYyu
I am looking for a library which would do something like that:
Lib.Configure.Cells(...)
Lib.CreateExcelFileFromMyObject<MyObject>(myObject);
I believe a long ago I come across such library but cant remember it's name.
May be some one can point me to the right direction.
I know two ways to read or write excel files.
As already said you can access excel files through the office interop interface as described here. This method is slow, but you can do almost everything what you can do with the gui of excel.
Use the OleDb database interface. This possibility is much faster than the first one, but its restricted to data. So as far as i know it is not possible to read/write formatting e.g. some background color of a cell. With the following function you will get the entire data of a sheet of an excel file at once:
private DataSet ConnectAndLoad(string filepath, string sheet)
{
DataSet data_set = new DataSet();
OleDbConnection oledbConn = new OleDbConnection(String.Format("Provider=Microsoft.Ace.Oledb.12.0;Data Source={0};Extended Properties=\"Excel 8.0;HDR=Yes;IMEX=1;\"", filepath));
string query = "Select * From [" + sheet + "$]";
try
{
oledbConn.Open();
OleDbCommand oledbCmd = new OleDbCommand(query, oledbConn);
OleDbDataAdapter ole_da = new OleDbDataAdapter(oledbCmd);
ole_da.Fill(data_set);
}
catch (OleDbException ex)
{
// do some error catching
}
finally
{
oledbConn.Close();
}
return data_set;
}
you can use
using Microsoft.Office.Interop
namespace to access the ms products
For that first you need to do is add that reference to your project
I'm having a problem opening a DBF file - I need to open it, read everything and process it. I tried several solutions (ODBC/OLEDB), several connection string, but nothing worked so far.
The problem is, when I execute the SQL command to get everything from the file, nothing gets returned - no rows. What's even more odd, the content of the DBF file being opened get deleted.
See the code I have:
public override bool OpenFile(string fileName, string subFileName = "")
{
OleDbConnection con = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + Path.GetDirectoryName(fileName) + ";Extended Properties=dBASE IV;User ID=;Password=;");
try
{
if (con.State == ConnectionState.Closed) { con.Open(); }
OleDbDataAdapter da = new OleDbDataAdapter("select * from " + Path.GetFileName(fileName), con);
DataSet ds = new DataSet();
da.Fill(ds);
con.Close();
int i = ds.Tables[0].Rows.Count;
return true;
}
catch
{
return false;
}
}
I debugged the code and watched the file being opend in Windows Explorer. When it reached this line:
da.Fill(ds);
the size of the file dropped to only a few Bytes (from hundreds of kB).
My next thought was to make the DBF file read only. That however cause an "unexpected exception from an external driver".
So my question is - what the heck? I'm sure the file is not corrupt, it is a direct export from some DB. (No, I do not have access to that DB). I can also open that file in MS Office no problem.
I cannot share the DBF file - it contains confidential data.
Two things... just because its a .DBF file extension might night mean its a Dbase IV file. It might actually be that of Visual Foxpro. That said, I would look into downloading and installing the Visual Foxpro OleDB driver from Microsoft download. Next, the OleDbConnection is pointing to the path that has the actual tables (you already have that).
The query itself, shouldn't care about the extension, so I would change your call to get just then name via "Path.GetFileNameWithoutExtension"
It might be a combination of the two.
Connection string for VFP provider
"Provider=VFPOLEDB.1;Data Source=" + FullPathToDatabase
This is not the exact answer but it will help you to find the issue.
Try to give an inline connection string and select query to make sure problem is not with building those. Catch the exception and check the details of it.
OleDbConnection con = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=c:\folder;Extended Properties=dBASE IV;User ID=;Password=;"); // give your path directly
try
{
con.Open();
OleDbDataAdapter da = new OleDbDataAdapter("select * from tblCustomers.DBF", con); // update this query with your table name
DataSet ds = new DataSet();
da.Fill(ds);
con.Close();
int i = ds.Tables[0].Rows.Count;
return true;
}
catch(Exception e)
{
var error = e.ToString();
// check error details
return false;
}
private void Form1_Load(object sender, EventArgs e)
{
GetDataTable(#"C:\Documents and Settings\agordon\Desktop\ACTIVITYEX.log");
}
public System.Data.DataTable GetDataTable(string strFileName)
{
System.Data.OleDb.OleDbConnection conn =
new System.Data.OleDb.OleDbConnection
("Provider=Microsoft.Jet.OleDb.4.0; Data Source = "
+ System.IO.Path.GetDirectoryName(strFileName)
+ ";Extended Properties = \"Text;HDR=YES;FMT=TabDelimited\"");
conn.Open();
string strQuery = "SELECT * FROM [" + System.IO.Path.GetFileName(strFileName) + "]";
System.Data.OleDb.OleDbDataAdapter adapter = new System.Data.OleDb.OleDbDataAdapter(strQuery, conn);
System.Data.DataTable ds = new System.Data.DataTable("CSV File");
adapter.Fill(ds);
return ds;
}
when THE SAME file is named .csv it does not give me an error; however when i rename it to .log it says Cannot update. Database or object is read-only. on adapter.Fill
is this a compiler error?
An old post, but I just stepped into that problem.
Please refer to this article : https://support.microsoft.com/en-us/kb/245407
Long story short : Jet Engine only accepts a few file extension when reading CSV File (Extended properties=TEXT,etc..).
Solutions :
rename your file in a temp folder when reading it
read it with another mecanism than JET (standard File.io.ReadAllLines)
Add the extension in the windows registry as pointed out by antonio Bukala
No, it's a not a compiler error. If anything it's an error from the OleDb Jet engine. I have ran into enough problems with Jet in the past so I usually avoid it. You might save yourself lots of debugging time by using TextFieldParser.
*.log is disabled extension, AFAIK only way is registry change on machine that will run this code, see MS Knowledge base article
I got some data inputed by the user that should be added to a Database File (.sdf). I've choose Sql Server CE because this application is quite small, and i didn't saw need to work with a service based database.
Well any way.
Here goes the code:
public class SqlActions
{
string conStr = String.Format("Data Source = " + new System.IO.FileInfo(System.Reflection.Assembly.GetExecutingAssembly().Location).DirectoryName + "\\basedados.sdf");
public SqlCeConnection SQLCEConnect()
{
SqlCeConnection Connection = new SqlCeConnection(conStr);
Connection.Open();
return Connection;
}
public Boolean AdicionarAuditorio(string Nome, int Capacidade)
{
string Query = "INSERT INTO auditorios (nome, capacidade) VALUES (#Nome, #Capacidade)";
using (var SQLCmd = new SqlCeCommand(Query, SQLCEConnect()))
{
SQLCmd.Parameters.AddWithValue("#Nome", Nome);
SQLCmd.Parameters.AddWithValue("#Capacidade", Capacidade);
if (SQLCmd.ExecuteNonQuery() == 1)
{
return true;
} else {
return false;
}
}
}
}
I use the AdicionarAuditorio(string Nome, int Capacidade) function to Insert the data. running ExecuteNonQuery() which is supposed to return the number of affected rows after he as run the query.
So it should return 1 if the query as successful, right?
In the end he returns 1, but if I browser the table data, the data that the query should add isn't there.
So whats wrong here?
NOTE. If your thinking that the
problem is the connection: I can't see
why is the problem once i got some
Select statements that use that
connection function SQLCEConnect()
and they all work pretty well.
Thanks in advance.
Are you sure you are looking at the right file? When you build your app in VS, it copies the SDF file as content to the target folder, so the database in your project will not reflect any updates. Your code is picking up the the file location there.
This is btw not a good practice, because once deployed, the program folders are not writable to your app (could this be the problem - did you already deploy?). Instead, the database file should reside in your appdata folder.
Is it possible that you make the call to AdicionarAuditorio in a TransactionScope without calling transactionScope.Complete()?