How to create a blank excel file using C# forms? - c#

I can't seem to create a new blank excel file so I can write in it with excel Interop later
System.IO.FileStream fs =(System.IO.FileStream)saveFileDialog1.OpenFile();
switch (saveFileDialog1.FilterIndex)
{
case 1:
//write blank xlsx?
break;
case 2:
//write blank xls?
break;
}
fs.Close();
ExportDataSetToExcel(_destinationDataSet, saveFileDialog1.FileName);
If I pass an empty file I got this error
Cant open file because the file format or file extension is not valid.
Verify that the file has not been corrupted and that the file
extension matches the format of the file.
So.. How can I create an empty xls or xls file?

Simplest way
var app = new Microsoft.Office.Interop.Excel.Application();
var wb = app.Workbooks.Add();
wb.SaveAs("File Path.xlsx");
wb.Close();

Empty Excel files are not simple empty files, since they also store some header data. One modern way of writing Excel files is to use Open XML SDK 2.5 as indicated here:
var spreadsheetDocument = SpreadsheetDocument.Create(filepath, SpreadsheetDocumentType.Workbook);
By doing so, you get a reference that allows you to write data to the Excel file.
In order to get a value for filepath, you can you use SaveFileDialog to indicate path to be used like indicated in the documentation:
var saveFileDialog1 = new SaveFileDialog();
saveFileDialog1.Filter = "Excel files|*.xlsx";
saveFileDialog1.Title = "Save an Image File";
saveFileDialog1.ShowDialog();
if(saveFileDialog1.FileName != "")
{
// file name is available here
}
You can make your Excel manipulation in C# even easier by using a third party library such as EPPlus.
Disclaimer: Above hints work only for the Excel 2007 and above formats.

I ended up doing this...
if (saveFileDialog1.FileName != "")
{
var app = new Application();
var wb = app.Workbooks.Add();
switch (saveFileDialog1.FilterIndex)
{
case 1:
wb.SaveAs(saveFileDialog1.FileName);
break;
case 2:
wb.SaveAs(saveFileDialog1.FileName, XlFileFormat.xlExcel8);
break;
}
wb.Close();
app.Quit();
ExportDataSetToExcel(_destinationDataSet, saveFileDialog1.FileName);
}

Related

VSTO C# - How to edit a .xltx file and don't save it as new file

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);

Removing vbaProject.bin in XML not enough to save as xlsx

After exporting data into an Excel workbook with macros (xlsm), I run the macro and then remove the macro in order to be able to save the workbook as xlsx. For removing macros, I open the xlsm as zip archive (via C# ZipFile class), remove the entry "xl/vbaProject.bin" and remove a relation within "xl/_rels/workbook.xml.rels". Then I rename the file from xlsm to xlsx. That works fine so far but when I open the xlsx file in Excel, I get "Excel cannot open the file because the file format or file extension is not valid. Verify that the file has not been corrupted and that the file extension matches the format of the file", so there seems something to be missing in order to completely remove the vba code within the workbook. Can anyone help me here?
const string vbaProjectEntryName = "xl/vbaProject.bin"; // Contains the VBA code
const string relationsEntryName = "xl/_rels/workbook.xml.rels"; // Relation/Link to the vba project
using (var zip = ZipFile.Open(fileName, ZipArchiveMode.Update))
{
var entry = zip.GetEntry(vbaProjectEntryName);
if (entry != null)
{
entry.Delete();
entry = zip.GetEntry(relationsEntryName);
if (entry != null)
{
var contents = string.Empty;
using (var streamReader = new StreamReader(entry.Open()))
{
contents = streamReader.ReadToEnd();
}
var relationText = "<Relationship Id=\"rId6\" Type=\"http://schemas.microsoft.com/office/2006/relationships/vbaProject\" Target=\"vbaProject.bin\"/>";
contents = contents.Replace(relationText, string.Empty);
entry.Delete();
entry = zip.CreateEntry(relationsEntryName);
using (var streamWriter = new StreamWriter(entry.Open()))
{
streamWriter.Write(contents);
}
}
}
}

Create a temporary excel file with epplus?

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

Saving HTML from MemoryStream into a Excel file

I have a XSLT transformed HTML data in MemoryStream (in C#). I am trying to convert this to an Excel format before emailing, preferably conversion happens all in memory again without saving to local disk. I can worry about the email attachment part later. Can anyone point me to a sample on how I could do the conversion from HTML to Excel format either through OpenXML or with Office.Interop.Excel.
The HTML data is well formed and I could manually do the conversion by opening the html in Excel application and do a Save As to save it in xlsx format (Office 2010), no problem. I also tried to simply change the .html extension to .xlsx, but then excel complains about opening it.
What's the best way to automate the manual SaveAs action so that I could use the same html data in Excel format? I understand that I could create a separate .xslt for directly converting my XML into Excel format. But, that'll be too many .xslt to maintain. I'm trying to find the hack to let Excel do the work for me.
Thank you for any and all pointers in advance!
EDIT:
I figured I have no choice but to store html to disk and read it back and use Excel Interop to do SaveAs method. When I did try though, getting the exception with HRESULT: 0x800A03EC on the SaveAs method. Here's how to reproduce it.
steps to reproduce the behavior
Save this text
<html><head></head><body><center><h1>Test Header</h1></center></body></html>
as C:\Test.html
after making reference to Excel interop like this,
using Excel = Microsoft.Office.Interop.Excel;
Try this code
`
var app = new Excel.Application();
Excel.Workbook wb = null;
try
{
wb = app.Workbooks.Open(#"c:\test.html");
wb.SaveAs(#"c:\test.xlsx", Excel.XlFileFormat.xlOpenDocumentSpreadsheet);
//wb.SaveCopyAs(#"c:\test.xlsx");
wb.Close();
}
catch (Exception ex)
{
//_logger.Error(ex);
}
finally
{
app.Quit();
}
`
I always get the mentioned exception on SaveAs no matter which fileformat I choose or even not mentioning the fileformat there..
Any ideas?
This code works. It turns out the exception I was getting is only related to the file format I was trying to save. When I changed it to Open XML workbook, it saved fine.
using Excel = Microsoft.Office.Interop.Excel;
.
.
.
var app = new Excel.Application();
Excel.Workbook wb = null;
try
{
wb = app.Workbooks.Open(#"c:\test.html");
wb.SaveAs(#"c:\test.xlsx", Excel.XlFileFormat.xlOpenXMLWorkbook);
//wb.SaveCopyAs(#"c:\test.xlsx");
wb.Close();
}
catch (Exception ex)
{
//_logger.Error(ex);
}
finally
{
app.Quit();
}
Here's the updated code that takes bytes[] html as input and returns xlsx in bytes[]
public static byte[] DoConvertXlDataToOpenXml(byte[] data, FileInfo fileInfo)
{
ExcelInterop.Application excelApp = null;
ExcelInterop.Workbooks workBooks = null;
ExcelInterop.Workbook workBook = null;
FileInfo tempFile = null;
FileInfo convertedTempFile = null;
try
{
//Stream the file to temporary location, overwrite if exists
tempFile = new FileInfo(Path.ChangeExtension(Path.Combine(Path.GetTempFileName()), fileInfo.Extension));
using (var destStream = new FileStream(tempFile.FullName, FileMode.Create, FileAccess.Write))
{
destStream.Write(data, 0, data.Length);
}
//open original
excelApp = new ExcelInterop.Application();
excelApp.Visible = false;
excelApp.DisplayAlerts = false;
workBooks = excelApp.Workbooks;
workBook = workBooks.Open(tempFile.FullName);
convertedTempFile = new FileInfo(Path.ChangeExtension(Path.GetTempFileName(), "XLSX"));
//Save as XLSX
excelApp.Application.ActiveWorkbook.SaveAs(
convertedTempFile.FullName
, Microsoft.Office.Interop.Excel.XlFileFormat.xlOpenXMLWorkbook
, ConflictResolution: ExcelInterop.XlSaveConflictResolution.xlLocalSessionChanges);
excelApp.Application.ActiveWorkbook.Close();
return File.ReadAllBytes(convertedTempFile.FullName);
}
catch (Exception)
{
throw;
}
finally
{
if (workBooks != null)
Marshal.ReleaseComObject(workBooks);
if (workBook != null)
Marshal.ReleaseComObject(workBook);
if (excelApp != null)
Marshal.ReleaseComObject(excelApp);
if (tempFile != null && tempFile.Exists)
tempFile.Delete();
if (convertedTempFile != null && convertedTempFile.Exists)
{
convertedTempFile.Delete();
}
}
}

How to Create/Open Excel files using OpenXml with C#

I have a console application in which we are creating xlsx files using OPENXML, we are able to create xlsx file & save it into specific folder in application.
But Now we want to show that file as a Save/Open dialog pop up. Then we can able to specify a particular path to save/ to open the existing files.
I am new to this OpenXml, Can anyone please help me on this to proceed further? How can I acheive this? Do we have any built-in DLL for this?
Thanks.
se the Save file dialog. It will prompts the user to select a location for saving a file. After that you can use saveFileDialog.FileName.ToString() property to get the full path.
See the sample code below:
//Save a file in a particular format as specified in the saveAsType parameter
private void OpenSaveFileDialog(int saveAsType)
{
SaveFileDialog saveFileDialog = new SaveFileDialog();
saveFileDialog.InitialDirectory = Convert.ToString(Environment.SpecialFolder.MyDocuments);
saveFileDialog.Filter = "CSV|*.csv|Excel|*.xlsx";
saveFileDialog.FilterIndex = saveAsType;
saveFileDialog.Title = "Save Data";
saveFileDialog.FileName = "My File";
saveFileDialog.ShowDialog();
if (saveFileDialog.FileName != "")
{
//File Path = m_fileName
m_fileName = saveFileDialog.FileName.ToString();
//FilterIndex property is one-based.
switch (saveFileDialog.FilterIndex)
{
case 1:
m_fileType = 1;
break;
case 2:
m_fileType = 2;
break;
}
}
}
Ref:http://msdn.microsoft.com/en-us//library/system.windows.forms.savefiledialog.aspx

Categories

Resources