All I want to do is to create a file with 1 line and few columns to make some test.
However I cannot find a simple way to do such a thing. Most help I found seem to also use a database.
I found one that doesn't.
Trying to create a new .xlsx file using NPOI and write to it
However it seems like a little too much for such a simple task. Is there a tool which would allow me to do something as simple as
Create file
file.cell[0,0] = ...
You could use the EPPlus package. Find it on NuGet.
string fileName = #"C:\test\MyNewExcelFile.xlsx";
FileInfo newFile = new FileInfo(fileName);
using (ExcelPackage xlPackage = new ExcelPackage(newFile)) // create the xlsx file
{
// Add a new worksheet on which to put data
ExcelWorksheet xlWorksheet = xlPackage.Workbook.Worksheets.Add("Test");
// Write data to cell(s)
xlWorksheet.Cells["A1"] = ...
// Write the file
xlPackage.Save();
}
EDIT
Modification to replace worksheet if it already exists.
const string fileName = #"C:\test\MyNewExcelFile.xlsx";
const string sheetName = #"test";
FileInfo newFile = new FileInfo(fileName);
using (ExcelPackage xlPackage = new ExcelPackage(newFile)) // create the xlsx file
{
// if sheet already exists, delete it
// use LINQ to query collection of worksheets
ExcelWorksheet xlWorksheet = xlPackage.Workbook.Worksheets.SingleOrDefault(ws => ws.Name == sheetName);
if (xlWorksheet != null)
{
// worksheet exists - delete it
xlPackage.Workbook.Worksheets.Delete(sheetName);
}
// Add new worksheet on which to put data
ExcelWorksheet xlWorksheet = xlPackage.Workbook.Worksheets.Add("Test");
// Write data to cell(s)
xlWorksheet.Cells["A1"] = ...
// Write the file
xlPackage.Save();
}
Related
I tried to use Spire.Xls library, but it does not support .xlsm and when i convert it to .xlsx hasn`t saved it, same with Microsoft.Office.Excel.Interop.
private void button1_Click(object sender, EventArgs e)
{
//string xlsm = #"D:\foot_Regular B07BNJ56GV B07BNK8S3Q B07BMX2NN4 with3.xlsm";
string xlsx = #"D:\foot_Regular B07BNJ56GV B07BNK8S3Q B07BMX2NN4 with3.xlsx";
//ConverXlsmToXlsx(xlsm, xlsx);
//string xlsx = #"D:\1.xlsx";
/* Load Excel File */
Excel.Application excelApp = new Excel.Application();
Excel.Workbook excelWorkbook = excelApp.Workbooks.Open(xlsx, 0, true, 5, "", "", true, Microsoft.Office.Interop.Excel.XlPlatform.xlWindows, "\t", false, false, 0, true, 1, 0);
/* Load worksheets collection */
Excel.Sheets excelSheets = excelWorkbook.Worksheets;
/* Select first worksheet */
Excel.Worksheet excelWorksheet = (Excel.Worksheet)excelSheets[1];
/* Deleting first 87 Rows */
Excel.Range range = excelWorksheet.get_Range("1:87").EntireRow;
range.Delete(Excel.XlDeleteShiftDirection.xlShiftUp);
/* Save File */
excelWorkbook.SaveAs(#"D:\out_file.xlsx");
excelWorkbook.Close(false);
excelApp.Application.Quit();
/* Release COM objects otherwise Excel remain running */
releaseObject(range);
releaseObject(excelWorkbook);
releaseObject(excelWorksheet);
releaseObject(excelApp);
MessageBox.Show("Finished");
}
Conver function:
public static void ConverXlsmToXlsx(string path, string outputPath)
{
byte[] byteArray = File.ReadAllBytes(path);
using (MemoryStream stream = new MemoryStream())
{
stream.Write(byteArray, 0, (int)byteArray.Length);
using (SpreadsheetDocument spreadsheetDoc = SpreadsheetDocument.Open(stream, true))
{
// Change from template type to workbook type
spreadsheetDoc.ChangeDocumentType(SpreadsheetDocumentType.Workbook);
}
File.WriteAllBytes(outputPath, stream.ToArray());
}
}
How i can easy work with .xlsm files via C#?
Help please with it, I would really appreciate it.
EPPlus seems to be the library to use.
You don't need Interop or an actual installation of MS Excel.
They have a sample how to work with VBA macros, but it seems your problem was just reading and saving files without touching the macros, so you should be good with their basic samples:
using (ExcelPackage package = new ExcelPackage(newFile))
{
// make your modifications
package.Save();
}
I personally use ClosedXML.
ClosedXML makes it easier for developers to create Excel 2007+ (.xlsx, .xlsm, etc) files. It provides a nice object oriented way to manipulate the files (similar to VBA) without dealing with the hassles of XML Documents. It can be used by any .NET language like C# and VisualBasic.NET.
You can find more details here.
Spire.XLS supports .xlsm files, here is the code to directly delete rows from a xlsm file with it:
Workbook workbook = new Workbook();
workbook.LoadFromFile("Input.xlsm");
Worksheet sheet = workbook.Worksheets[0];
sheet.DeleteRow(1,87);
workbook.SaveToFile("Output.xlsm", ExcelVersion.Version2007);
I use the Spire.XLS Pack(Hotfix) Version:8.6.6
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 a macro-enabled Excel file "D:\MyTests\ExcelTests\template.xlsm" with no data in it, only the VBA code, and my C# code needs to output a workbook data over there. Normally I output workbook data like this:
Excel.Application application = new Excel.Application();
Excel.Workbook workbook = application.Workbooks.Add();
Excel.Worksheet worksheet = workbook.Sheets[1];
Excel.Worksheet worksheet2 = workbook.Sheets[2];
// populate worksheets with some data
DataTable2Worksheet(tableMain, worksheet, verSize);
DataTable2Worksheet(tableExtra, worksheet2, 0);
string fileName = #"D:\MyTests\ExcelTests\newFile";
if (File.Exists(fileName ))
{
File.Delete(fileName );
}
workbook.SaveAs(fileName);
workbook.Close();
Marshal.ReleaseComObject(application);
but this creates a new file (which cannot be macros enabled programmatically). If I want to output the workbook to existing file
string existingFile = #"D:\MyTests\ExcelTests\template.xlsm"
the method
workbook.SaveAs(existingFile );
won't work. So, what should I do instead? Thanks.
Save the file specifically in xlOpenXMLWorkbookMacroEnabled format:
string existingFile = #"D:\MyTests\ExcelTests\template.xlsm"
workbook.SaveAs(existingFile, 52);
I would like to simply copy one sheet within my workbook and give it a different name.
var pointName1 = workbook.Worksheets["PointName1"] as Worksheet;
pointName1.Copy(); // How do I access this newly created sheet?
Ideally I would like be able to write a method like this
pointName1.CopyTo("New Sheet");
where 'New Sheet' is a renamed copy of 'PointName1'.
Sometimes PointName1 will be the only sheet in the workbook, other times there will be others.
You can achieve this in multiple ways - probably the easiest way is to copy after the last sheet and then rename it using the index:
Excel.Application xlApp = Marshal.GetActiveObject("Excel.Application") as Excel.Application;
Excel.Workbook xlWb = xlApp.ActiveWorkbook as Excel.Workbook;
Excel.Worksheet xlSht = xlWb.Sheets[1];
xlSht.Copy(Type.Missing, xlWb.Sheets[xlWb.Sheets.Count]); // copy
xlWb.Sheets[xlWb.Sheets.Count].Name = "NEW SHEET"; // rename
I believe this MSDN guide also answers your question.
If you want to get the index of a sheet, look up Worksheet.Index property.
You should be able to use the Copy function, but you won't be able to rename the sheet in the same step. The MSDN documentation shows the additional parameters:
pointName1.Copy(pointName1, Type.Missing); //Place a copy before the existing sheet
From the documentation:
If you do not specify either Before or After, Microsoft Office Excel creates a new workbook that contains the copied sheet.
To rename the sheet you'll need to get a reference to the new sheet (by index or name) and use the Name property of worksheet to change the name.
EDIT:
If you use the code above you can use the index of the original sheet (since you're placing the copy before the original):
int index = pointName1.Index;
pointName1.Copy(pointName1, Type.Missing);
Worksheet newWS = (Worksheet)xlApp.Worksheets[index];
well, other solution mentioned here did not work for me. I got this solution.
Step 1: Create a copy of the source file (i.e. TempFile )
Step 2: Copy desired sheet of source file to TempFile
Step 3: Delete the source file
Step 4: Rename TempFile to Source File.
Note: You will need the "Microsoft.Office.Interop.Excel" package from
Nuget for this solution. Also, add using Excel = Microsoft.Office.Interop.Excel;
static void Main(string[] args)
{
Excel.Application excelApp;
string sourceFileName = "Original.xlsx"; //Source excel file
string tempFileName = "temp.xlsx";
string folderPath = #"C:\FodlerPath\";
string sourceFilePath = System.IO.Path.Combine(folderPath, sourceFileName);
string destinationFilePath = System.IO.Path.Combine(folderPath, tempFileName);
System.IO.File.Copy(sourceFilePath,destinationFilePath,true);
/************************************************************************************/
excelApp = new Excel.Application();
Excel.Workbook wbSource, wbTarget;
Excel.Worksheet currentSheet;
wbSource = excelApp.Workbooks.Open(sourceFilePath);
wbTarget = excelApp.Workbooks.Open(destinationFilePath);
currentSheet = wbSource.Worksheets["Sheet1"]; //Sheet which you want to copy
currentSheet.Name = "TempSheet"; //Give a name to destination sheet
currentSheet.Copy(wbTarget.Worksheets[1]); //Actual copy
wbSource.Close(false);
wbTarget.Close(true);
excelApp.Quit();
System.IO.File.Delete(sourceFilePath);
System.IO.File.Move(destinationFilePath, sourceFilePath);
}
The easiest way is to copy it after the last sheet as presented in the accepted answer.
Please note that if the excel file contains hidden sheets, the copy will be place between the visible sheets and the hidden ones, therefore the hidden sheets will be pushed to the right.
If you then try to set the name with xlWb.Sheets[xlWb.Sheets.Count].Name = "NEW SHEET" you will end up renaming your last hidden sheet instead of your new copy.
I have managed to get round this by accessing the new copy by it's name: xlWb.Sheets["_oldName_ (2)"].Name = "NEW SHEET".
Other fix that will enable you to use xlWb.Sheets[xlWb.Sheets.Count].Name = "NEW SHEET" is to set all sheets visible before copying the desired sheet.
Using EPPlus I want to add a new sheet to an Excel file but I do not want to delete the existing sheets in the file if any, and I want to insert it as the first sheet in the file.
Here is what I have written for a quick test but it deletes all the existing sheets:
using (ExcelPackage p = new ExcelPackage())
{
p.Workbook.Worksheets.Add("HubaHuba");
p.Workbook.Worksheets.MoveToStart("HubaHuba");
ExcelWorksheet ws = p.Workbook.Worksheets[1];
ws.Name = "HubaHuba";
var cell = ws.Cells[1, 1];
cell.Value = "dfsdfsdfsd";
cell = ws.Cells[1, 2];
cell.Value = "347895y5 Oh";
Byte[] bin = p.GetAsByteArray();
File.WriteAllBytes(path,bin);
}
using (ExcelPackage excelEngine = new ExcelPackage())
{
excelEngine.Workbook.Worksheets.Add("sheet1");
excelEngine.Workbook.Worksheets.Add("sheet2");
excelEngine.Workbook.Worksheets.Add("sheet3");
String myFile= "c:\....\xx.xlsx";
excelEngine.SaveAs();
}
When you use Add the sheet is added at the and of current file sheets.
If you want to add in a specific position use this function:
excelEngine.Workbook.Worksheets.Add("sheet0");
excelEngine.Workbook.Worksheets.MoveBefore(4, 1);
sheet0 is added at the and in 4th position and you move it in first position with the previous code.
That's because you're rewriting the file with command File.WriteAllBytes. Instead you should just call p.Save() and ExcelPackage needs to use the constructor that accepts the file path. Then it will work.