I'm having an issue saving excel files as CSV's and preserving the encoding in C#. Specifically, the following takes an excel file and saves it as a csv file with the same name, which is passed to the loadCsvData function, whose job is to insert the data into a database in an organized fashion. My issue is that the excel file contains fractional symbols which are not recognized in a csv format, unless i MANUALLY open each .xml and save as csv (for some reason this works while the Microsoft.Office.Interop.Excel.Application method SaveAs() does not):
List<string[]> data = new List<string[]>();
string fileName = (date.ToString("MM/dd/yyyy") + ".csv").Replace("/","");
string excelFileName = (date.ToString("MM/dd/yyyy") + ".xml").Replace("/","");
System.Console.WriteLine("Processing file: " + fileName);
System.Console.ReadLine();
// Open excel and save as csv. Then process the data
Microsoft.Office.Interop.Excel.Application app = new Microsoft.Office.Interop.Excel.Application();
Microsoft.Office.Interop.Excel.Workbook workBook = app.Workbooks.Open(#"C:\Users\TAG\Desktop\TIP holdings\" + excelFileName);
workBook.SaveAs(#"C:\Users\TAG\Desktop\TIP holdings\CSV Data\" + fileName, Microsoft.Office.Interop.Excel.XlFileFormat.xlCSV);
workBook.Close(false,"",true);
data = loadCsvData(fileName);
insertData(data);
Related
I can't figure out why this isn't working with a XLTX file. My code is wokring quite well with XLSX files.
/// <summary>
/// Copies the template file and renames the new one.
/// </summary>
/// <param name="sourceFilePath"></param>
private void CopyTemplateFile(string sourceFilePath)
{
string strSheetName = "";
DialogResult result;
result = MyDialog.ShowDialog("New File - Dialog", "Bitte Name eingeben", "Neue Datei erstellen?", "=FOR1+RBT1", "Ok", "Cancel", ref strSheetName);
if (result == DialogResult.Yes)
{
SaveFileDialog sfd = new SaveFileDialog();
sfd.Filter = "Excel Template (*.xltx)|*.xltx|Excel File (*.xlsx)|*.xlsx";
sfd.FileName = strSheetName;
DialogResult ergebnis = sfd.ShowDialog();
if (ergebnis == DialogResult.OK)
{
string path = sfd.FileName;
//string tmp = path.Substring(path.LastIndexOf('\\')+1);
System.IO.File.Copy(sourceFilePath, path);
Excel.Application app = new Excel.Application();
Excel.Workbook wb = app.Workbooks.Open(path, ReadOnly: false);
Excel.Worksheet ws = (Excel.Worksheet)wb.Worksheets.get_Item(1);
ws.Name = strSheetName;
ws.Range[Statics.ANLAGE_ORT_CELL].Cells.Value2 = "'" + strSheetName;
string stAnlage = strSheetName.Substring(1);
string[] abc = stAnlage.Split('+');
ws.Range["A50"].Cells.Value2 = abc[0];
ws.Range["B50"].Cells.Value2 = abc[1];
wb.SaveAs(path);
wb.Close();
app.Quit();
Marshal.ReleaseComObject(app);
}
}
}
I'm using Microsoft.Office.Interop.Excel, a open file dialog for sourceFilePath, a save file dialog for path. The changes of sheet.name and cell values aren't saved if a XLTX is used.
Maybe someone of you guys knows the issue.
The issue is this line:
wb.SaveAs(path);
According to the documentation of the Workbook.SaveAs method you can/should give the following parameters:
FileName
A string that indicates the name of the file to be saved. You can include a full path; if you don't, Microsoft Excel saves the file in the current folder.
FileFormat
The file format to use when you save the file. For a list of valid choices, see the XlFileFormat enumeration. For an existing file, the default format is the last file format specified; for a new file, the default is the format of the version of Excel being used.
Actually both are optional, but if you omit the FileName Excel will use the standad file name and the "current folder" who knows which one this is, and if you omit the FileFormat then Excel would use the last file format that was specified or for new files the standard format which is a normal xlsx (in recent versions of Excel).
Another thing is that the file extension you use .xltx, .xlsx, .xlsm necessarily needs to fit the correct file format. If it doesn't Excel throws an error. This is actually what you run into when you got the Error:
COMException: Additional information: This extension cannot be used
with the selected file type. Change the file extension in the 'File
Name' text box, or choose a different file type by changing the 'Save
As' selection.
Because you only specified the FileName and you chose .xltx as file extension but the default file format is usually xlOpenXMLWorkbook according to the list in XlFileFormat enumeration.
So if you lookup in that list which file formats you can use with the extension .xltx then you will only find one valid file format and that is xlOpenXMLTemplate. So this is what you need to specify:
'example for path/filename you got from your dialog box
path = "C:\YourPath\YourFileName.xltx"
wb.SaveAs(FileName:=path, FileFormat:=xlOpenXMLTemplate);
I have some code that is suppose to enter some values into several excel workbooks. Right now the program doesn't even put any values into the workbooks and only saves them. Even like this i get this error when opening the files: Excel cannot open the file **.xlsm because the file format or file extension is not valid. Verify that the file has been corrupted and that the file extension matches the format of the file.
I have writen many programs that work with excel files and never had this problem. In the code you can see that i basically just go through a for loop and save the file.
try
{
fileInfo = new FileInfo(Path.GetDirectoryName(Application.StartupPath) + '\\' + partners[partner].partnerName + #"\PDP_ExSumm_" + partners[partner].partnerName + ".xlsm");
using (ExcelPackage excelPackage = new ExcelPackage(fileInfo))
{
ExcelWorksheet worksheet = excelPackage.Workbook.Worksheets[1];
for (int cell = 0; cell < ExSummCells.Count; cell++)
{
if (ExSummCells[cell] != "")
{
// worksheet.Cells[ExSummCells[cell]].Value = partners[partner].exSummData[partner];
}
excelPackage.Save();
}
}
I have a requirement where I need to format input files from different resources. My application receives input (xls/xlsx/ibfs) files through file upload and performs condition checks and generates formatted output in .xlsx file format. All my input files are reports generated by different online public data reporting websites. When I downloaded in excel format some websites are producing in “WFServlet.ibfs” file formats.
This is not a duplicate post. I tried different approaches and followed suggestions here and tried several ways but didn't solve my issue. Sorry for the long post. I want to have seniors advise or help to solve this problem.
I’m able to handle xls and xlsx file formats with using C# OLEDB ACE engine. It’s working perfectly fine in my local machine and also in my locally hosted IIS server. But when I upload .ibfs file formats I’m getting issues.
Sample input
Here I'm posting my most effective two different approaches:
Approach 1 (Using Microsoft Office Interop)
Approach 2 (Using third party EPPlus library)
1. Approach 1 (Using Microsoft Office Interop):
In this approach, I used Microsoft Interop dlls. Initially before conversion I changed the extension of .ibfs to .xls and then I used Microsoft Interop to convert xls into xlsx file format. In this approach its working fine in my local machine. But it’s not working in my local IIS server (In my local IIS server I’m able change the extension from .ibfs to .xls but after that it’s not creating xlsx file from xls). I added dlls of Office12 "Microsoft.Office.Interop.Excel.dll" and "Office.dll" to my project reference.
But with this approach I may have a problem in future. Currently Office is installed in my local machine, but when we move code to the server there we don’t have Office installed and client don’t want to install Office in the server. I'm not sure whether it will work in the server with the same dll's without installing the office.
Below is the code:
Step 1: Change extention from .ibs to .xls and call conversion method, if user uploaded file is .ibfs file type
string path ="C:\\testinput\\";
string extension = Path.GetExtension(InputFile.FileName); // get the extension of user upload file
string fileName = "testFile"+ extension; // make a new name to assign to the user uplaoded file
InputFile.SaveAs(path + fileName); // save the user uploaded file into the testinput folder with testFile file name
inputFileWithPath = path + fileName; // copy the path of saved file "C:\\testinput\\testFile+extenstion"
newPath = inputFileWithPath; // used if input file is of .ibfs or .xls extn
if (extension.Equals(".IBFS") || extension.Equals(".ibfs"))
{
//input user uploaded file extension is .ibfs , If file already exist in the upload folder path then delete the old one before File.Move
if (File.Exists(newPath + ".ibfs"))
{
File.Delete(newPath);
}
else
{
newPath = Path.ChangeExtension(inputFileWithPath, ".xls"); // chnage the file extension from .ibfs to .xls
File.Move(inputFileWithPath, newPath); // move the new file .xls to testinput path
inputFileWithPath = excelComm.convertExel(newPath); // convert the .xls file into .xlsx file format
}
}
Step 2 Now conversion logic from .xls to xlsx using Interop
public string convertExel(string FilePath)
{
string path = "";
var app = new Microsoft.Office.Interop.Excel.Application();
try
{
if (File.Exists(FilePath + "x")) // check if file with .xlsx is already exist, if exist delete it
{ File.Delete(FilePath + "x"); }
else
{
var wb = app.Workbooks.Open(FilePath);
wb.SaveAs(Filename: FilePath + "x", FileFormat: Microsoft.Office.Interop.Excel.XlFileFormat.xlOpenXMLWorkbook);
path = FilePath + "x";
wb.Close();
}
} // end of try
catch (Exception ex)
{
string errorMsg = "";
CatchException(ex, errorMsg);
}
return path;
}
2. Approach 2 (Using third party EPPlus library):
I downloaded EPPlus.dll and added to my project reference. I used below code. Which is basically changes the extension of .ibfs to xls and calls the convertExcel methods, where it converts the xls into dataset from that dataset , I copied data table into to the workbook sheet and saved it as .xlsx file. But it is not working.
Below is the code sample
Step 1: Change extension from .ibs to .xls and call conversion method, if user uploaded file is .ibfs file type
Step 1 is same as above as mentioned in Approach 1.
Step 2: Conversion from .xls to xlsx using EPPlus library. For this I followed solution from C# - convert xls file to xlsx without office components
public string convertExel(string FilePath)
{
string path = "";
try
{
if (File.Exists(FilePath + "x"))// check if file with .xlsx is already exist, if exist delete it
{File.Delete(FilePath + "x");}
else
{
string fileName = Path.GetFileNameWithoutExtension(FilePath);
string filePathXlsx = "C:\\testinput\\"+ fileName + ".xlsx ";
using (ExcelPackage epackage = new ExcelPackage())
{
ExcelWorksheet excel = epackage.Workbook.Worksheets.Add("Sheet1");
DataSet ds = ReadExcelFile(FilePath); // Causing Error HERE
DataTable dtbl = ds.Tables[0];
excel.Cells["A1"].LoadFromDataTable(dtbl, true);
System.IO.FileInfo file = new System.IO.FileInfo(filePathXlsx);
epackage.SaveAs(file);
path = filePathXlsx;
} // end of using
}// end of else
}//end of try
catch (Exception ex)
{
string errorMsg = "";
CatchException(ex, errorMsg);
}
return path;
} // end of method
// generate dataset from excel file
private static DataSet ReadExcelFile(string FilePath)
{
string constr = "";
DataSet ds = new DataSet();
string extension = Path.GetExtension(FilePath);
if (extension.Equals(".xls", StringComparison.CurrentCultureIgnoreCase))//Checking for the extentions, if XLS connect using ACE OleDB
{
constr = "Provider=Microsoft.ACE.OLEDB.12.0;" + "Data Source=" + FilePath + ";Extended Properties=\"Excel 8.0;IMEX=1;HDR=YES\"";
}
//Use ACE OleDb if xlsx extention
else if (extension.Equals(".xlsx", StringComparison.CurrentCultureIgnoreCase))
{
constr = string.Format("Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};Extended Properties=\"Excel 12.0;IMEX=1;HDR=YES\"", FilePath);
}
else
{
constr = "Provider=Microsoft.ACE.OLEDB.12.0;" + "Data Source=" + FilePath + ";Extended Properties=\"Excel 8.0;IMEX=1;HDR=YES\"";
}
using (OleDbConnection conn = new OleDbConnection(constr))
{
conn.Open(); // causing error HERE
OleDbCommand cmd = new OleDbCommand();
cmd.Connection = conn;
DataTable dtSheet = conn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, new object[] { null, null, null, "TABLE" }); // Get all Sheets in Excel File
foreach (DataRow dr in dtSheet.Rows) // Loop through all Sheets to get data
{
string sheetName = dr["TABLE_NAME"].ToString();
cmd.CommandText = "SELECT * FROM [" + sheetName + "]"; // Get all rows from the Sheet
DataTable dt = new DataTable();
dt.TableName = sheetName;
OleDbDataAdapter da = new OleDbDataAdapter(cmd);
da.Fill(dt);
ds.Tables.Add(dt);
} // end of for
cmd = null;
conn.Close();
} // end of using
return ds;
}
Its giving me error “System.Data.OleDb.OleDbException (0x80004005): External table is not in the expected format.
at System.Data.OleDb.OleDbConnectionInternal..ctor(OleDbConnectionString constr, OleDbConnection connection)”
Its changing the extension from .ibfs to xls but after that its not generating any xlsx file. I tried with different connection strings, ACE, Jet engines with Xml format, HTML import, with single quotes and double quotes but nothing is working. Is it problem with the downloaded web excel file in any specific format which is not supported by OLEDB? I'm not sure how to handle such type of specific formats.
I appreciate if any one can give me any idea how I can solve the problem with the 'ibfs' file formats.
My Latest update: I tried with the Spire.XLS but it didn't work with '.ibfs' file formats. Its just working fine with xls and xlsx formats.
Just one request, please only suggest open-source dll's. I can't install any software in client machine (server). I have only option to use open-source libraries like EPPlus or anything supported by just dll's without any installation. Thank you.
Try replacing Extended Properties=\"Excel 12.0;IMEX=1;HDR=YES\" with Extended Properties=\"Excel 12.0 Xml;IMEX=1;HDR=YES\" in
//Use ACE OleDb if xlsx extention
else if (extension.Equals(".xlsx", StringComparison.CurrentCultureIgnoreCase))
{
constr = string.Format("Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};Extended Properties=\"Excel 12.0;IMEX=1;HDR=YES\"", FilePath);
}
If IBFS files are Excel files, you can try using Essential XlsIO. I couldn't find any IBFS files to check with.
The whole suite of controls is available for free (commercial applications also) through the community license program if you qualify. The community license is the full product with no limitations or watermarks.
Note: I work for Syncfusion.
After adding all I want to a newly created excel file with epplus, how do I open it only? I don't want to save the file first then open it, is this possible? I want it to just open and let the user decide if he wants to save it or not.
The only code i've found and tried so far generates a file name, saves the excel file, and then open it.
Byte[] bin = p.GetAsByteArray();
string file = Guid.NewGuid().ToString() + ".xlsx";
File.WriteAllBytes(file, bin);
ProcessStartInfo pi = new ProcessStartInfo(file);
Process.Start(pi);
EPPlus is generating the xml in a renamed zip file so there is no mechanism to transfer it to Excel without saving it somewhere. But you can always save to the users temp folder - this is what most programs have to do at some point in order to transfer files between each other. Can do something like this using System.IO.Path.GetTempPath():
[TestMethod]
public void TempFolderTest()
{
var path = Path.Combine(Path.GetTempPath(), "temp.xlsx");
var tempfile = new FileInfo(path);
if (tempfile.Exists)
tempfile.Delete();
//Save the file
using (var pck = new ExcelPackage(tempfile))
{
var ws = pck.Workbook.Worksheets.Add("Demo");
ws.Cells[1, 2].Value = "Excel Test";
pck.Save();
}
//open the file
Process.Start(tempfile.FullName);
}
(taken from: Open ExcelPackage Object with Excel application without saving it on local file path)
it's not possible you can't Create a temporary excel file with epplus
I have tool for parsing excel files. User chooses the xls/xlsx to be read, then my tool creates a copy of it in the temp with a random name, then actually parses the copy. The relevant part of the code:
string sourceFile = textBox1.Text;
string fileName = System.IO.Path.GetRandomFileName();
string destFile = System.IO.Path.Combine(Path.GetTempPath(), fileName + ".xlsx");
System.IO.File.Copy(sourceFile, destFile, true);
Microsoft.Office.Interop.Excel.Application xlApp = new Microsoft.Office.Interop.Excel.Application();
Microsoft.Office.Interop.Excel.Workbook excelBook = xlApp.Workbooks.Open(destFile);
OleDbConnection cnn = new OleDbConnection(#"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + destFile + "; Extended Properties=Excel 12.0;");
string qText = #"select * from [sheet1$]";
OleDbCommand oconn = new OleDbCommand(qText, cnn);
cnn.Open();
OleDbDataAdapter adp = new OleDbDataAdapter(oconn);
DataTable dt = new DataTable();
adp.Fill(dt);
cnn.Close();
And then I start to work with the DataTable.
In case the original source files (not the copy) is open in excel, then the copy from the temp folder also opens up in excel. And here comes the strangest stuff. If it's closed during the script run, and then I open the original xls only from windows explorer, the copy from temp opens up again. Moreover, if I run the script e.g. 10 times (while original is closed), when I open it, all the 10 randomly named copies open up along with it. I suppose it's not due to the code itself, but some windows/office bug/feature.
Please advise.
You have two lines here that initializes and open the copy of your destination file
Microsoft.Office.Interop.Excel.Application xlApp = new Microsoft.Office.Interop.Excel.Application();
Microsoft.Office.Interop.Excel.Workbook excelBook = xlApp.Workbooks.Open(destFile);
You should remove them. OleDb interaction with the Excel file doesn't need Interop to work.
By the way, when working with these ugly Interop variables I use a simple trick to shorten these names
using ExcelLib = Microsoft.Office.Interop.Excel;
.....
ExcelLib.Application xlApp = new ExcelLib.Application();